KVO接口说明
注册:addObserver:forKeyPath:options:context:
例如
[self.busModel addObserver: self forKeyPath: @"name" options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOldcontext:@"bus name"];
1>.self.busModel :要监听的对象
2>.self 观察者,负责处理监听事件的对象
3>.监听的属性
4>.观察的选项(例如新值)
5>.上下文,用于传递数据,可以利用它区分不同的监听
属性改变时调用的方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
1>.监听的属性
2>.属性所属对象
3>.属性的变化
4>.上下文
Apple的文档对 KVO 实现的描述:
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ...
并未过多的暴露内部实现的细节:是通过isa-swizzling(isa混编)来实现的
其实当我们观察一个对象时,会动态的创建一个新类,这个类继承与我们所观察的对象所在的类,并重写了观察对象的属性的setter方法,在setter方法中实现真正的通知机制:
如图:
1.每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统会偷偷将isa(isa 指针告诉 Runtime 系统这个对象的类是什么)指针指向动态生成新类,从而在给被监控属性赋值时执行的是派生类的setter方法
2.键值观察通知依赖于 NSObject 的两个方法:willChangeValueForKey:和didChangevlueForKey:。在一个被观察属性发生改变之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后didChangeValueForKey:也会被调用,在observers列表中检查是否有该属性,有的话observeValueForKey:ofObject:change:context:也会被调用
经测试observeValueForKey是在didChangeValueForKey执行时调用的