@Observable修饰符是干啥的?

571 阅读4分钟

swiftui的修饰符确实让人头疼,一个是修饰符长的特别像,另一个是语言更新迭代导致一些功能重复但是新的关键词的诞生。

@binding 修饰符

先说一下我的理解吧。前一篇文章中讲解了@state的修饰符。可以让数据更新后,自动更新视图。 另一种情况就是双向绑定,数值更新了,自动更新ui。当ui更新了,也对应的自动更新数值,比如输入框。

话说好像木有学习过输入框咧。过一下。看了下基本的输入。

image.png 注意,此处用到了美元符号。

image.png

可以看到参数并非是string,Binding ,这是什么呢?

image.png 可以发现是一个结构体,前面还用了一堆修饰符。我讨厌修饰符。

image.png

一个属性包装器类型----可以读取和写入一个值---被一个source of truth所拥有。不明所以。不过有一个例子。

image.png

image.png

可以看到playerview中的isplaying,被传递到了playbutton中,而playbutton中使用的就是@binding,而不是@state。
看了下大概意思是,binding不存储数据,而是绑定数据的真实来源。比如playerview中的state修饰的变量isplaying存储的是真实的数据。虽然playbutton中也定义了一个isplaying,但是仅仅是关联到父视图的isplayer的值而已。

Applying the $ prefix to a property wrapped value returns its projectedValue, which for a state property wrapper returns a binding to the value.

使用美元符号前缀到一个属性包装器的值,可以得到它的projectedvalue。

image.png

看起来就是一个get方法,获取到绑定的这个属性的值。

这个绑定值传递到子视图中,子视图进行修改,是可以同步更改到父视图的,从而实现双向绑定。




@Observable

言归正传,该说说正主了。
我是在学习的项目里用到了

@Observable

class ModelData{

    **var** landmarks:[Landmark] = load("landmarkData.json")

    **var** hikes:[Hike] = load("hikeData.json")

    **var** categorys: [String:[Landmark]] {

        Dictionary(grouping: landmarks) { landmark **in**

            landmark.category.rawValue

        }

    }

}

此处有一个class,然后看里面定义了几个变量,不知道为啥这里定义了一个。让我去掉看看哪里会报错,就知道它起什么作用了

image.png

可以发现此处报错了,大意是: 实例方法,environment要求ModelData遵循Observable协议。不过,我有一个问题,

@Observable和Observable是一回事吗?

image.png

按住option键,鼠标点击可以看到如图内容。查看完成说明

image.png

不过看完了还是一头雾水。 定义和实现Observable协议。 该宏定义添加观察者支持---给自定义的类型,并且,让这个类型遵循Observable协议。例如car就可以被观察了。 所以会提供一个默认实现吗?

Observable协议干啥用的?啥时候用?

点击到这个协议的说明页面

image.png

一个类型---发射通知到观察者,当下划线的数据改变的时候。 遵循该协议,发生信号到其他的api---这个类型是支持被观察的。 然而,应用这个协议给一个类型,本身不会添加观察者,函数式的。 相反,始终使用Observable()宏定义,当给一个类型添加观察支持的时候。

看起来是说,这个协议是允许一个自定义的类型被观察,但是使用的时候不要直接使用该协议,而是使用Observable(),也机会说@Observable。

我不知道是不是这样理解。但是怎么没有看到这个协议的说明呢?另外这个宏定义又做了什么?

image.png 看起来就是一个空协议呢?虽然定义空协议的情况也是存在的,只需要判断是否遵循了某协议,就可以做一些逻辑判断,不知道此处是不是如此。

看的意思是说Observable和@Bindable的出现是为了取代以往的ObservableObject、@Published。在swift5.9之前。 如果要观察一个自定义类型中属性的变化,并实现双向绑定,要这样实现。

image.png

iShot_2024-11-13_16.08.51.gif

看图,就是swift5.9之前的针对自定义类型要进行双向绑定的话,需要让对象遵循ObservableObject协议,然后属性还要声明为@Published,最后,在定义一个@ObservedObject修饰这个对象。

而在swift5.9之后。则简化了。

iShot_2024-11-13_16.12.45.gif