学习记录,仅供参考。欢迎指正!!!
本质是 调用了 属性的 setter方法
前提 新建 MLPerson类, 设置 int类型的age属性
一、 设置属性的值 添加KVo监听 查看监听前后的类对象的地址值变化
1. 这里使用 runtime 的API object_getClass 获取实例对象 的isa指向的类对象
由此可见,person1实例对象 设置KVO监听之后,isa指向的类对象发生了变化,指向了一个由runtime动态生成的一个类 NSKVONotifying_XXX. 且这个类是 原来类XXX的一个子类。
二、查看添加KVO监听前后 元类对象的变化
设置监听前后的 类对象也发生了变化
说明:新生成的 子类 NSKVONotifying_XXX 的isa 指向的是 一个新的元类对象。
三、查看添加监听前后的方法的具体实现
设置监听之前:调用的是 MLPerson 里边的 setAge:方法
设置监听之后:调用的是新的子类里边的 setAge:方法,只不过 里边调用了 Foundation框架 里边的 _NSSetIntValueAndNofify方法
四、窥探 _NSSetIntValueAndNofify 方法实现
1、 当监听到 person1 的age属相值发生了变化之后,首先调用 新生成的子类的 setAge:方法
setAge:方法里边调用的是 Foundation 框架 的 _NSSetIntValueAndNotify方法
右下图可知
_NSSetIntValueAndNotify的内部实现
①.先调用了 willChangeValueForKey:方法
②.接着调用 父类的 setAge:方法(也就是MLPerson里边的setAge方法,使age的值真正发生变化)
③. 发生变化之后 会接着调用 didChangeValueForKey: 方法
在此方法内部,通知监听器 某个对象的 属性值 发生了变化 接着触发 KVO的监听方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context;
五、如果修改了 成员变量会不会触发KVO?
不会。因为没有调用 setter方法
六、如何手动触发KVO
手动调用 willChangeValueForKey 和 didChangeValueForKey方法