KVO梳理
1.KVO实际是KVO<NSKeyValueObserving>,是一个非正式协议
2.作用是观察者对象监听被观察对象的属性,当被观察对象的属性发生变化时,观察者对象会被告知。
3.添加方法 (手动调用)
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
参数分析
object : 被观察对象
observer: 观察者对象
forKeyPath:属性
options: 策略枚举 分别是
NSKeyValueObservingOptionNew 响应方法中的change字典会包含监听属性的新值
NSKeyValueObservingOptionOld 响应方法中的change字典会包含监听属性的旧值
NSKeyValueObservingOptionInitial 响应方法中的change字典会包含监听属性的初始值,立即调用一次。
NSKeyValueObservingOptionPrior 值改变前后分别调用一次响应方法。
context: 任意类型参数 类型是void * 在响应方法中需要强转 例:NSString*typeStr = (__bridgeNSString*)context;
4.响应方法 (手动实现)
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary*)change context:(nullable void *)context;
参数分析
keyPath: 监听的属性
object: 被观察的对象
change: 一个字典类型
context: 对应context
实现原理
1.KVO是基于runtime机制实现的,当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,例如TestClass会生成NSKVONotifying_TestClass,在这个派生类中重写基类中任何被观察属性的setter 方法。派生类在被重写的setter方法内实现真正的通知机制
2.每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统会将isa指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的setter方法
3.键值观察通知依赖于NSObject 的两个方法: willChangeValueForKey: 和 didChangevlueForKey:;在一个被观察属性发生改变之前, willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,didChangeValueForKey:会被调用,继而 observeValueForKey:ofObject:change:context: 也会被调用。