State
A property wrapper type that can read and write a value managed by SwiftUI.
SwiftUI manages the storage of any property you declare as a state. When the state value changes, the view invalidates its appearance and recomputes the body. Use the state as the single source of truth for a given view.
A State instance isn’t the value itself; it’s a means of reading and writing the value. To access a state’s underlying value, use its variable name, which returns the wrappedValue property value.
ObservableObject
A type of object with a publisher that emits before the object has changed.
- ObservableObject是Combine框架下的协议类型,针对引用类型设计,用于在多个View之间共享数据
- 遵循ObservableObject协议的类型,需要实现objectWillChange属性,最简单的实现方式是使用系统提供的@Published,添加到对应需要监听的属性上,这个属性一般不能设置为private,因为可以被外部修改,但如果提供对外方法进行修改,可以改为private(set),即setter方法私有,getter方法默认等级
- 标记为@Published的属性在属性变化前发出变化值,使得对象类型的某个属性的数据改变得以被监听,并发出信号通知View更新
- 属性中添加@Published的值类型会在值变化后发出信号,比如struct,如果添加引用类型(嵌套对象)目前会有问题,它的属性变化不会发出信号,需要额外特殊处理(TODO)
- ObservableObject协议有一个名称为objectWillChange的publisher,他有几个特点: 这个publisher不发送数据 这个publisher不会失败,即Failure是Never 这个publisher只是发通知,Notification的作用 objectWillChange的类型是ObjectWillChangePublisher. 同时在ObservableObject协议的扩展中,系统默认已经实现了objectWillChange
StateObject
- 针对引用类型设计,当View更新时,实例不会被销毁,与State类似,使得View本身拥有数据
- @StateObject 和 @ObservedObject 的区别就是实例是否被创建其的View所持有,其生命周期是否完全可控。
- StateObject行为类似ObservedObject对象,区别是StateObject由SwiftUI负责针对一个指定的View,创建和管理一个实例对象,不管多少次View更新,都能够使用本地对象数据而不丢失
- @StateObject就是一个针对 class 的 @State 升级版
StateObject两种初始化方式
定义时直接赋初值
@StateObject var counter: Counter = Counter() //1
通过Property wrapper的init方法赋值
@StateObject var counter: Counter
init(counter: Counter) {
self._counter = StateObject(wrappedValue: counter) //2
//self.counter = counter //3
}
注释2处是正确方式,注释3处是错误的,提示Cannot assign to property: 'counter' is a get-only property
那么第二种通过wrappedValue进行初始化的方式什么时候需要使用呢?这与你希望为状态设置初始值的原因是相同的:如果你特别希望根据视图的参数设置初始值,然后让视图从那里管理状态,你就需要这种方式。
ObservedObject
- 只是作为View的数据依赖,不被View持有,View更新时ObservedObject对象可能会被销毁
- 适合数据在SwiftUI外部存储,把@ObservedObject包裹的数据作为视图的依赖,比如数据库中存储的数据
- @StateObject的声明周期与当前所在View生命周期保持一致,即当View被销毁后,StateObject的数据销毁,当View被刷新时,StateObject的数据会保持;而ObservedObject不被View持有,生命周期不一定与View一致,即数据可能被保持或者销毁;