自己使用swift4.0写了一个例子
class FirstViewController: UIViewController {
@objc dynamic var age = 0
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
self.addObserver(self, forKeyPath: "age", options: [NSKeyValueObservingOptions.old, NSKeyValueObservingOptions.new], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "age" {
if let newValue = change?[NSKeyValueChangeKey.newKey] {
print("age changed: \(newValue)")
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.age += 1
}
注意事项
- 观察者和被观察者都必须是 NSObject 的子类;
- 观察的属性需要使用 @dynamic 关键字修饰。
- 条件1:观察者和被观察者都必须是NSObject的子类,因为OC中KVO的实现基于KVC和runtime机制,只有是NSObject的子类才能利用这些特性。
- 条件2:要观察的属性使用@dynamic修饰,表示该属性的存取都由runtime在运行时来决定,由于Swift基于效率的考量默认禁止了动态派发机制,因此要加上该修饰来开启动态派发;除此之外,在NSObject子类中几乎没有属性默认是使用@dynamic修饰,所以若想对某个属性进行观察,还必须在当前的子类中override该属性,override时,采用super的实现即可。