SwiftUI: State, StateObject, ObservedObject, ObservableObject

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一致,即数据可能被保持或者销毁;

About Tang

A mobile developer, work in Stockholm, Sweden
This entry was posted in iOS and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s