在Swift中,观察者属性允许对属性值的改变做出反应。这个概念伴随着Swift的出现,旨在提高对数据变化的控制透明度,并在变化时自动化逻辑。
问题背景:
在Swift之前,这种行为通常通过setter或特殊方法手动实现。在Swift中,观察者作为语言的标准工具出现。
问题:
开发者需要能够捕捉到属性值变化的时刻,例如,用于更新UI或验证数据。没有观察者,代码会变得更冗长且不易读取。
解决方案:
在Swift中,有两个主要的观察者可供使用:
willSet在值改变之前被调用didSet在赋值后被调用观察者可以添加到存储属性(stored property),但不能添加到延迟属性(lazy properties)和计算属性(computed properties)上。
代码示例:
class Temperature { var celsius: Double { willSet { print("即将设置值", newValue) } didSet { print("之前的值是:", oldValue, ", 现在是:", celsius) } } init(celsius: Double) { self.celsius = celsius } } let temp = Temperature(celsius: 22) temp.celsius = 28 // 会输出willSet和didSet
关键特点:
可以向计算属性添加观察者吗?
不可以,计算属性不能添加willSet和didSet,因为它们已经有自己的getter和setter。使用willSet/didSet仅适用于存储属性。
在初始化器内部更改属性时,观察者会被调用吗?
不会,属性观察者在初始化(init)期间不会被调用。它们只在init结束后更改值时被触发。
当将当前值赋值给自己,例如x = x时,会发生什么?
观察者仍然会被调用,即使属性值没有改变!这可能导致副作用,所以要小心。
var value: Int = 0 { didSet { print("didSet总是被调用!") } } value = value // didSet会被调用
开发者在didSet中实现了UI更新,但没有控制值的变化。在"空"赋值时,UI仍然会更新,导致性能下降。
优点:
缺点:
在didSet中检查旧值和新值的相等性。只有在值确实改变时才更新UI。
优点:
缺点: