SwiftUI视图刷新机制杂谈
笼统的说,属性在被改变时想要触发视图refresh,需要满足下面两种条件之一:
- 该对象是值类型,所有值类型都不能被修改,只能创建修改后的实例。这使得SwiftUI运行时可以捕获到这种新创建的时机,借此刷新视图。
- 该对象是引用类型,遵守ObservableObject协议,由其中的objectWillChange发布器被SwiftUI订阅(隐式),从而在收到对象被修改时刷新视图。
这意味着如果你用@State修饰引用类型,则不会刷新界面。Apple称这种行为是:未定义的!即: 可能刷新也可能不刷新。
大家当然都不想依赖这种未定义的行为。
为什么我一上来要说这些呢?因为后面会用到引用类型属性的自动刷新。
@propertyWrapper利器
Swift 5.1在为我们带来SwiftUI和Combine的同时,也为我们创建自定义属性打开方便之门。
如果你之前还在羡慕@State,@FetchRequest之类的属性修饰器的强大和便捷,那么现在则完全没有必要了: 你可以自己定制类似的属性修饰器了,而定制的不二法门就是使用@propertyWrapper修饰关键字。
理论谈再多也感觉到懵懂,下面照例用一个例子来说明:
假设我们的App的状态需要放到UserDefaults中,以便持久存储,我们如何兼顾状态改变和View的即时刷新呢?
我们将会用代码来说明,如何自定义属性包装器来完成该