如果给某对象设置kvo监听那么该对象的isa会指向NSKVONotifying_XXX
通过打印isa可得知已变成NSKVONotifying_XXX对象
p self.student.isa
(Class) $0 = NSKVONotifying_person
Fix-it applied, fixed expression was:
self.student->isa
NSKVONotifying_XXX 这个是runtime动态创建的一个类
1、iOS 用什么方式实现对一个对象的kvo?(kvo的本质是什么)
利用runtimeApi动态新生成一个类,并且让instance对象的isa指向新生成的这个类
当修改instance对象的属性时,会调用Foundation的_NSSet***ValueAndNotify的函数
willChangeValueForKey
父类原来的setter
didChangeValueForKey
内部会触发监听器(oberser)的监听方法observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
2、子类内部的方法
新生成的NSKVONotifying_XXX 会生成
set方法 class方法 ,dealloc方法 ,_isKVOA 方法
3、如何手动触发kvo?
手动调用willChangeValueForKey和didChangeValueForKey
4、直接修改成员变量会触发kvo么?
KVO
键值观察者 (Key-Value Observer):是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。
简单的说就是:观察者A监听被观察者B的某个属性,当B的属性发生更改时,A就会收到通知,执行相应的方法。
实现原理
2416132-074e1fd08a54d564.png基本的原理:当观察对象A时,KVO机制动态创建一个对象A的子类 NSKVONotifying_A,该类继承自对象A,并为这个新的子类重写观察属性keyPath的setter 方法。setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象属性值的更改情况。在这个过程,被观察对象的 isa 指针从指向原来的A类,被KVO机制修改为指向系统新创建的子类NSKVONotifying_A类,来实现当前类属性值改变的监听
如何手动实现KVO?
[person willChangeValueForKey:@"name"];
person.sex= 1;
[person didChangeValueForKey:@"name"];
键值观察通知依赖于 NSObject 的两个方法: willChangeValueForKey: 和 didChangeValueForKey。在一个被观察属性发生改变之前, willChangeValueForKey: 一定会被调用,这就 会记录旧的值。而当改变发生后, didChangeValueForKey 会被调用,继而 observeValueForKey:ofObject:change:context: 也会被调用。如果可以手动实现这些调用,就可以实现“手动触发”了 有人可能会问只调用didChangeValueForKey方法可以触发KVO方法,其实是不能的,因为willChangeValueForKey: 记录旧的值,如果不记录旧的值,那就没有改变一说了
网友评论