您的位置:首页 > 其它

KVC/KVO的实现原理简述

2016-03-25 20:57 232 查看

一、KVC

KVC全称为key-value coding,键值编码。就是提供了一种机制可以访问一个对象的任意属性。它是通过使用字符串作为关键字而不是使用setter/getter访问器去访问一个对象实例的属性的机制。

1.1 实现原理:

(问题:KVC是如何访问属性的)

(1)如果是取值操作,检查是否存在-,-is,或者-get的对应key的访问器方法,如果有则调用这些方法。

如果是设值操作,检查是否存在-set方法,并使用它来进行属性设值。对于get和set岂会遵循Cocoa方法命名规范,把key首字符大写,所以我们平时也要注意属性和方法的命名规范!

(2)如上如方法不可用,则检查是否存在对应的 -_,-_is,-_get和-_set方法。

(3)如果没有找到访问器方法,则尝试直接访问成员变量。其名一般为或_。

(4)如果仍未找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey方法。这两个方法默认会抛出异常,我们也可以重写这些方法进行对应情况的处理。

二、KVO

KVO全程为key-value observing,键值观察。提供了一种当指定的对象的属性发生变化时,则通知所有的观察者的机制。通常用于model和controller之间。

2.1 实现原理:

(1)KVC和KVO都和一种叫isa-swizzling的技术有关,其依赖于runtime机制提供的强大动态能力。

(2)当某个类的实例第一次被观察时,系统会在运行期间动态的创建一个该类的派生类,在这个派生类会重写父类中被观察属性的setter方法。

派生类中被重写的setter方法实现了真正的通知机制。这么做的原因是根据KVC的实现机制,我们会发现其修改属性的实质就是通过调用属性的访问器进行的。所以如果遵循KVO的属性设置方式来修改属性值,就可以实现对属性修改的观察;否则的话,如果直接修改属性对应的成员变量值,是无法实现KVO的。

(3)同时该派生类还重写了class方法,以“欺骗”外部调用者,让它们还以为它还是原来的那个类。然后系统将这个对象的isa指针指向这个派生类的Class实例,其实际是这个实例早以成为派生类的对象了。所以使用者调用属性的访问器修改属性时实际上是调用了派生类中重写的setter方法,从而激活了键值通知的机制。此外,派生类也重写了dealloc方法来释放资源。

2.1 重点

派生类会在setter方法中增加两个方法的调用。

- (void)willChangeValueForKey:(NSString *)key
- (void)didChangeValueForKey:(NSString *)key


其中,会在didChangeValueForKey:里调用观察者的这个方法。

- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context


以上就是KVO的实现原理了!

为了唤醒键值观察(KVO),也可以手动调用will/didChangeValueForKey。

参考资料

KVC/KVO原理详解及编程指南
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编码 对象