浅析KVO、KVC

KVO

Key-Value Observing,“键值监听”:用于监听某一对象属性值的改变。

某一对象被监听后,系统利用 Runtime API 对该对象的原始类动态生成一个 “NSKVONotifying_CPPerson” 子类,并且让 instance 对象的 isa 指针指向这个子类。

在新生成的这个子类中会重写父类的 setAge:classdealloc_isKVOA 四个方法。

当被监听对象的属性值发生改变后,会在 setAge: 方法中调用 NSFoundation 的 “_NSSetIntValueAndNotify” 函数。且在该函数内部重写了父类的 willChangeValueForKey:setAge:didChangeValueForKey:方法。

并且在 didChangeValueForKey:方法中出发监听器 Observe 的监听方法 “observeValueForKeyPath: ofObject: change: context:”。

本质:

  • 由于 KVO 的本质是重写了原始类的 Setter 方法,所以像直接修改成员变量是不会触发监听方法的。

  • 若想手动触发监听器的监听方法:手动执行 willChangeValueForKey:didChangeValueForKey:方法。

KVC

Key-Value Coding,“键值编码”:可以通过某一个 key 来访问对应的属性。

KVC 不管有没有调用 setter 方法,都会触发 KVO 的监听方法。因为它会手动触发监听。

赋值操作:setValue: forKey:

  • 首先会寻找 setAge:_setAge: 两个方法的实现。

  • 若没有,会通过 accessInstanceVariablesDirectly 方法判断是否允许访问成员变量,若为 YES,则访问的顺序为 _age_isAgeageisAge

取值操作:valueForKey:

  • 首先会寻找 getAge:age:isAge:_age: 四个方法的实现。

  • 若没有,同上。