KVO与KVC原理笔记

KVO的实现原理

当咱们对A类添加监听的时候,系统会自动生成一个NSKVONotifying_A的子类,这个类重写了A的class、superclass、deealloc方法和该属性的Set方法,同时A类的对象的isa指针指向了该虚拟子类。当监听属性改变的时候系统调用NSSetobjectValueandNotify,这个方法的执行流程是(willchangeValueforkey->改变父类的值->didchangeValueforkey->observeValueForKey:ofObject:change:context:),若是设置automaticallyNotifiesObserversForKey:(NSString *)key为NO的时候则须要手动触发KVO即手动调用willchangeValueforkey和didchangeValueforkey.html

func _NSSetObjectValueAndNotify {
    ...
    willchangeValueforkey
    ...
    " objc_msgSendSupper '改变父类的值(猜想这样实现) "
    ...
    didchangeValueforkey
    ...
    observeValueForKey:ofObject:change:context: 
}

复制代码

Q1: 为何重写系统的class/superclass、deealloc方法

由于该子类为系统自动生成苹果想假装成并无这个类 因此重写class/superclass ,可是调用 objc_getClass()这个方法时候依然会暴露,由于这个方法是调用调用对象的isa指针指向。dealloc则是系统还有一些其余的事情处理数组

Q2:为何KVO要实现一个子类

KVC是什么,他是如何实现的

KVCKVC是由NSKeyValueCoding非正式协议实现的一种机制,对象采用该协议来提供对其属性的间接访问。当一个对象符合键值编码时,它的属性能够经过一个简洁、统一的消息传递接口经过字符串参数来寻址。这种间接访问机制补充了实例变量及其关联的访问方法所提供的直接访问。bash

valueForkey的查找流程

  1. 在实例中搜索找到的类里面的相关方法,其名称依次为get<Key>, <key>, is<Key>, or _<key>。若是找到,则调用它,并继续执行步骤5的结果。不然继续下一步。
  2. 若是没有找到那么搜索countOf<Key> and objectIn<Key>AtIndex:,若是找到了其中的第一个和另外两个中的至少一个,则建立一个collection代理对象,该对象响应全部NSarray方法并返回该对象, 若是没有找到数组相关方法那么搜索countOf<Key>, enumeratorOf<Key>, and memberOf<Key>:,若是实现了其中一个则该对象响应全部Set方法的,
  3. 若是上述方法都没有找到那么判断accessInstanceVariablesDirectly 属性是否为yes,若是为yes则查找**_<key>, _is<Key>, <key>, or is<Key>**属性,若是找到直接返回变量值
  4. 若是都没找到那么且accessInstanceVariablesDirectly为false,那么执行valueForUndefinedKey:方法,调用valueForUndefinedKey:,默认状况下,这会引起异常,但NSObject的子类可能提供关键的特定行为

setValueForkey的实现

set value:for key:的默认实现:给定key和value参数做为输入,尝试在接收调用的对象内,使用如下过程将名为key的属性设置为value(对于非对象属性,则设置未包装的value版本,如表示非对象值:app

  1. 按此顺序查找名为set<key> 和 **_set<key>**的第方法。若是找到了,使用value值调用它并完成。
  2. 若是找不到简单访问器,而且类方法accessInstanceVariablesDirectly返回Yes,则按该顺序查找名为 _<key>、_is<key>、<key>或is<key>的实例变量。若是找到,直接用value设置。
  3. 在找不到方法或实例变量时,调用setValue:ForUndefinedKey:。默认状况下,这会引起异常,但NSObject的子类可能提供关键的特定行为。
相关文章
相关标签/搜索