KVO底层实现原理

KVO的本质

key-value observer,键值监听,对某一个实例对象进行该实例对象某一个属性值的监听addObserver:forKeyPath:options:content:对象添加监听的方法

参数

observer,需要谁(实例对象)来监听

keyPath,需要监听的属性名称 不是所有的属性都可以监听

options,监听该属性的方式 新值 / 旧值

content,携带值,一般为nil

KVO 不会对self进行强引用,如果观察者的生命周期结束了,self被释放,所以添加的监听需要被移除。

iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)

利用RuntimeAPI动态生成一个子类NSKVONotifying,并且让instance对象的isa指向这个全新的子类,当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数willChangeValueForKey:

父类原来的setter

didChangeValueForKey:

内部会触发监听器(Oberser)的监听方法(observeValueForKeyPath:ofObject:change:context:)

如何手动触发KVO?

手动调用willChangeValueForKey:和didChangeValueForKey:

KVO

kvo

未使用KVO监听的对象

实例对象的isa指针指向类对象,因为类对象在内存中存储的信息有isa指针,superclass,属性,对象方法,协议,成员变量等,因此可以在类对象中找到对象方法,进行调用。
使用了KVO监听的对象

当一个实例对象调用添加监听属性的方法时,实际上是runtime动态创建了一个名为“NSKVONotifying_Person类名”的类,该类会继承与person类,并且让该实例对象的isa指针重新指向了这个动态创建的类的类对象。因此在该实例对象属性修改值的时候,实际上在内存中该实例对象通过isa指针找到了动态创建的这个子类的类对象,这个动态的类对象中重写了属性的set方法,只是这个动态类的set方法实现并不是直接修改该属性的值,而是调用了一个名叫 “_NSSetIntValueAndNotify的C方法。

_NSSetIntValueAndNotify方法的内部实现,相当于在调用原来的set方法实现之前,加入 willChangeValueForKey,在其方法后,加入didChangeValueForKey,以此来记录属性的新值和旧值。然后在重写didChangeValueForKey方法中,通过调用 observer的observerValueForKeyPath:ofObject:change:content方法通知监听者。

NSSetxxxValueAndNotify内部实现

直接修改成员变量会触发KVO吗?

不会 因为没有调用set方法,KVO的本质就是重写set方法

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容