为什么说 KVO 是基于 KVC 实现的
在阅读本篇文章之前,需要你了解 KVC 和 KVO 的基本实现,如不清楚,可先阅读下面两篇文档KVC 的基本使用和KVO 的基本使用
在学习 KVO 的时候,看很多文章都说 KVO 是基于 KVC 实现的
KVO 实现原理(只针对普通对象,不包括集合)
当某个类的属性被观察时,系统会在运行时动态的创建一个该类的子类。并且把改对象的 isa 指向这个子类
假设被观察的属性名是
name,若父类里有setName:或这_setName:,那么在子类里重写这 2 个方法,若 2 个方法同时存在,则只会重写setName:一个(这里和 KVCset 时的搜索顺序是一样的)若被观察的类型是 NSString,那么重写的方法的实现会指向
_NSSetObjectValueAndNotify这个函数,这个函数里会调用willChangeValueForKey:和didChangevlueForKey:,并且会在这 2 个方法调用之间,调用父类 set 方法的实现系统会在
willChangeValueForKey:对 observe 里的 change[old]赋值,取值是用valueForKey:取值的,didChangevlueForKey:对 observe 里的 change[new]赋值,然后调用 observe 的这个方法- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;当使用 KVC 赋值的时候,在 NSObject 里的
setValue:forKey:方法里,若父类不存在setName:或这_setName:这些方法,会调用_NSSetValueAndNotifyForKeyInIvar这个函数,这个函数里同样也会调用willChangeValueForKey:和didChangevlueForKey:,若存在则调用
为什么说 KVO 基于 KVC 实现的
当使用 KVO 观察某个类属性时,会为该类创建一个子类,子类重写 setter 方法时,跟 KVCset 时的搜索顺序是一样的,都是先搜索 set
,然后在搜_set 。对于 KVC,若不存在会有后续操作,参考上面的文档 在为
observe的 change 字典里的 old 和 new 赋值时,用到了 KVC 的valueForKey:也许是苹果在 KVO 文档里的这句话。为了理解 KVO,你首先要理解 KVC
Important: In order to understand key-value observing, you must first understand key-value coding.