KVO
listen
以类 CLPerson 为例
age 属性
未监听 CLPerson
isa 指向 CLPerson 类对象
class 方法返回自己
KVO监听之后 CLPerson
isa指针指向了一个叫NSKVONotifying_CLPerson的class对象
class 方法被重写,返回 CLPerson
重写了setAge方法
重写了 dealloc
增加了_isKVOA方法
监听之后元类是不一样的, 并且一个类添加监听之后,新增的KVO类并不会动态
删除,会留在缓存
重写 setAge
调用_NSSetIntValueAndNotify()函数
调用[self willChangeValueForKey:@"age"];
再调用父类(CLPerson)的setAge方法[super setAge:age];
[self didChangeValueForKey:@"age"];
[self didChangeValueForKey:@"age"];方法里面对监听器进行通知,也就是回
调它的监听代理方法
总结
iOS用什么方式实现对一个对象的KVO?(KVO的本质)
1.利用Runtime API为被监听对象动态生成一个子类,并且让instance对象的isa
指向这个新的子类
2.在新的子类中重写属性的setter方法。当instance对象属性被修改的时候,该
setter方法被调用
3.在上述的setter方法里面,会调用Foundation对象的
_NSSetXXXValueAndNotify函数,该函数内部的主要逻辑是
3.1调用willChangeValueForKey:
3.2调用父类(也就是instance对象被监听之前,isa所指向的class)的setter
方法,进行成员变量赋值
3.3调用didChangeValueForKey:方法,该方法内部会触发监听器
(observer)的监听方法(observeValueForKeyPath: ofObject: change:
context:)
如何手动触发KVO
手动调用willChangeValueForKey:和didChangeValueForKey:即可
直接修改成员变量会触发KVO吗?
不会触发KVO
触发KVO的条件是通过属性值修改,触发了setter方法,从而触发KVO回调方
法,因此直接修改属性对应的成员变量值,不会触发KVO。