KVO究竟干了什么?

学习记录,仅供参考。欢迎指正!!!

本质是 调用了 属性的 setter方法


前提   新建  MLPerson类, 设置 int类型的age属性

一、 设置属性的值  添加KVo监听  查看监听前后的类对象的地址值变化

1. 这里使用 runtime 的API  object_getClass 获取实例对象 的isa指向的类对象

01

由此可见,person1实例对象 设置KVO监听之后,isa指向的类对象发生了变化,指向了一个由runtime动态生成的一个类 NSKVONotifying_XXX. 且这个类是 原来类XXX的一个子类。

二、查看添加KVO监听前后 元类对象的变化

设置监听前后的 类对象也发生了变化

说明:新生成的 子类 NSKVONotifying_XXX 的isa 指向的是 一个新的元类对象。

元类对象地址值

三、查看添加监听前后的方法的具体实现

设置监听之前:调用的是 MLPerson 里边的 setAge:方法

设置监听之后:调用的是新的子类里边的 setAge:方法,只不过 里边调用了 Foundation框架 里边的 _NSSetIntValueAndNofify方法

设置KVO监听前后方法的具体实现

四、窥探 _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 *)change context:(void *)context;

_NSSetIntValueAndNofify

五、如果修改了 成员变量会不会触发KVO?

不会。因为没有调用 setter方法

修改成员变量不会触发KVO监听

六、如何手动触发KVO

手动调用  willChangeValueForKey  和  didChangeValueForKey方法

手动触发KVO

你可能感兴趣的:(KVO究竟干了什么?)