简介
Key-Value Coding(以后都简称为KVC),是一种设计模式,其想法就是不用对对象的某个属性进行设置或者读取,而是使用key来访问。这种模式在Map中是很容易理解的,因为Map/Dictionary中保存的就是key-value 对,对这个pair进行操作,都是通过key来操作的。KVC就不仅仅限于Map/Dictionary,而是把它扩展到了普通对象。任何不同对象的instance variable都可以用KVC。使用KVC的好处就是可以将变量本身与他要关联的属性进行解耦,比如有个值,代表下载进度,进度一方面要在UI的进度条上显示出来,一方面用数字的方式显示在另一个地方(Console,Label on UI),这个值一改变,其关联的地方都要改,传统的方式就是一个一个地该,而基于KVC的方式,将这个值的key跟需要同步的属性关联,依赖KVC提供的互相更新的机制,就可以不用在代码中一个一个的改了。
实现KVC 有多种方式,在引用的文章里介绍了5种,我们分别探究一下其原理。
1. NSKeyValueCoding 协议
NSKeyValueCoding协议是informal的,其中定义了使用最多用于 set 和 get 的两个函数 setValue:forKey: 和 valueForKey:。 Cocoa使用Category on NSObject实现了这些方法,其他方法可以看NSKeyValueCoding协议doc。
优点
- 这种方法可以自动找到get/set 方法,即使get/set方法不存在,还可以之间操控ivars。因此大多数property 都自动支持这个功能了。
- 包含key的路径()?
- 与NSKeyValueObserving 集成,可以很容易实现Observer模式;
- 有fallback机制处理undefined key的情况;
缺点
- 其扩展的search path使其性能很差;
- 需要一个NSKeyValueCoding 能找到的方法或者ivar被定义在类中;
2. Manual subsets of NSKeyValueCoding behavior
NSKeyValueCoding 协议使用selector name找方法的名字,使用那么找ivar的名字。这种方法是可以自己实现的,这样就可以实现定制行为了:比如自己定的search path等。
优点
比NSKeyValueCoding协议方法相比,对lookup path有更多控制权;
可能比NSKeyValueCoding 快;??
对于非NSObject子类也可以用;
可以实现对对non-object 值的操作;
缺点
- 不如NSKeyValueCoding协议flexible;
- 大多数情况下,比NSKeyValueCoding协议需要更多work;
3. Associated objects
Objective C运行时允许将任何object与其他任一object关联,这就使得任一object可以拥有额外的一组使用key设置的property 集合。而不需要对象ivars或者方法提供支持。这种方法的适用环境是:从外界设置对象的属性(比如从没有对象的支持、?????)
优点
不需要对象提供特殊支持;
key可以是任何pointer;
有潜力是最快的KVC方式;
缺点
key是指针,不是对象,所以如果一个对象被使用时,它必须指向unique的对象;
不影响对象的ivas和method。也就是说,这个object并不知道KVC的进行,如果你需要这个对象知道这些变化,就需要使用其他方式。
4. selectors as keys
KVC的实现主要就是需找某个key对应的property,然后对这个property执行操作。Objective-C的runtime提供了这种以SEL查找的API:objc_msgSend。这种方式类似于部分实现NSKeyValueCoding 协议。这种方式最好使用SEL作为key。
优点
对方法遍历的最快方法;
可以get/set non-object数据(需要使用objc_msgSend_fpret 和 objc_msgSend_stret 等实现);
缺点
get/set需要不同的key
selector不是对象,所以不能在ObjC的array或者Dictionary中存储;
5. Do it by yourself
最后的办法就是自己实现,This is something you would do if you needed maximum flexibility (for handling unusual keys/values) or wanted to expose different key-value sets from a single object.
优点
- 一个对象可以暴露多个、独立的collection
- 可以get/set 底层collection支持的任何数据类型;
- 对fallback和处理特殊情况的最灵活的方法;
缺点
- 必须由target class实现;
- 不能跟NSKeyValueObserving 和NSKeyValueCoding配合使用;
引用:
1. http://disanji.net/2010/12/12/5-key-value-coding-approaches-in-cocoa-html/
2. http://www.cocoawithlove.com/2010/01/5-key-value-coding-approaches-in-cocoa.html