swift key-Value Observing
在swift中 只有继承 NSObject的类才具有 kvo特性
应用 kvo 的三个步骤
- 给属性添加
dynamic
修饰语 - 创建一个全局内容变量 用来标记观察者
- 加入到观察者中, 并在 deinit中 移除观察者
完整代码如下
import UIKit
//- [关于 kvo](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-ID12)
class MyObjectToObsever: NSObject {
// 要观察的属性 用 dynamic 修饰
dynamic var myDate = NSDate()
func updateDate(){
myDate = NSDate()
}
}
// 全局变量, 用来标记通知类型 也可以不标记
private var myContext = 0
class KVODemo: NSObject {
var objectToObserver = MyObjectToObsever()
override init() {
super.init()
// 把要观察的 属性加入观察中心
objectToObserver.addObserver(self, forKeyPath: #keyPath(MyObjectToObsever.myDate), options: .new, context: &myContext)
}
//当被观察的属性 值 发生变化时 会走这个方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if context == &myContext {
if let newValue = change?[.newKey] {
print("Date changed: \(newValue)")
}
}else{
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
//记得手动移除 观察者
deinit {
objectToObserver.removeObserver(self, forKeyPath: #keyPath(MyObjectToObsever.myDate))
}
}
dynamic关键字
如果您有过OC的开发经验,那一定会对OC中@dynamic关键字比较熟悉,它告诉编译器不要为属性合成getter和setter方法。
Swift中也有dynamic关键字,它可以用于修饰变量或函数,它的意思也与OC完全不同。它告诉编译器使用动态分发而不是静态分发。OC区别于其他语言的一个特点在于它的动态性,任何方法调用实际上都是消息分发,而Swift则尽可能做到静态分发。
因此,标记为dynamic的变量/函数会隐式的加上@objc关键字,它会使用OC的runtime机制。
虽然静态分发在效率上可能更好,不过一些app分析统计的库需要依赖动态分发的特性,动态的添加一些统计代码,这一点在Swift的静态分发机制下很难完成。这种情况下,虽然使用dynamic关键字会牺牲因为使用静态分发而获得的一些性能优化,但也依然是值得的。
class Kraken {
dynamic var imADynamicallyDispatchedString: String
dynamic func imADynamicallyDispatchedFunction() {
//Hooray for dynamic dispatch!
}
}
使用动态分发,您可以更好的与OC中runtime的一些特性(如CoreData,KVC/KVO)进行交互,不过如果您不能确定变量或函数会被动态的修改、添加或使用了Method-Swizzle,那么就不应该使用dynamic关键字,否则有可能程序崩溃。