观察者模式 在iOS开发中应用相当广泛,即:Key-Value Observing,它提供一种机制,当指定的对象的属性(相应的keyPath)被修改后,则对象就会接受到通知。简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知相应的观察者。
swift中使用KVO要比OC中稍显局限:
- NSObject的子类:观察者和被观察者都必须是 NSObject 的子类。 因为OC中KVO的实现基于 KVC 和 runtime 机制,只有是 NSObject 的子类才能利用这些特性。
- @dynamic:观察的自定义类的属性需要使用 @dynamic 关键字修饰。
以上这两个条件,就使得以往OC中的使用KVO来观察某个枚举属性的type的变化,在swift中就行不通,当然还包括了swift中的结构体以及泛型。
下面来看下swift中实现kvo
自定义类
import UIKit
class FLObbserve: NSObject {
dynamic var name:String? //dynamic 修饰属性 表示该属性的存取都由 runtime 在运行时来决定
override init() {
name = "123"
super.init()
addObserver(self, forKeyPath: "name", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("kvo is valid")
}
deinit {
removeObserver(self, forKeyPath: "name")
}
}
运行后,外部修改name
属性,控制台打印结果:
kvo is valid
由此在实现了上述两个条件后,为自定义类添加了kvo。
那么对于Struct,Enum这些值类型的如何实现观察者模式呢?
这边我们就要引入一个属性观察器的概念:
Swift 中可以为一个属性设置属性观察器,可以说是内建的 KVO 观察,只不过只限于对自身属性的观察。
看下代码:
//MARK: 设置自定义属性的属性观察器
var direction:Direction {
willSet{ // direction属性变化前要执行事件
}
didSet { // direction属性变化后要执行事件
changeDirection(direction: direction)
}
}
其中,Direction
是自定义的枚举
属性观察器只在在初始化完成后触发,而且不限于 NSObject 的子类,Swift 中所有的 Class, Struct, Enum 都可以使用。
其中,Array, Dictionary, Set 等值类型,对其内容的修改(增/删/替换)元素也会触发属性观察器。因为Array、Dictionary、Set 等值类型更改内容后,会将新的内容复制到变量,变量的地址也发现变化。
网友评论