KVC原理小记录

无意看到KVC原理的文章,发现很多中文文章说的都不全面,翻了一下官网文档,记录一下

basic getters

基础的valueForKey:

1.搜寻实例对象存取方法,搜寻的方法名顺序为:get<Key><key>,is<Key>或者_<key>,如果搜寻到了类似的方法,将结果带入第5步。否则进行下一步
2.如果没有找到简单的访问器方法,开始寻找符合countOf<Key>,objectIn<Key>AtIndex:(与NSArray类的初始方法相对应地方法,参数也与NSArray的对应方法一样)和<key>AtIndexs:(与NSArray的objectsAtIndexes:对应)这种命名规则的方法。如果第一个方法(countOf<Key>)和剩下两个方法中的至少一个被发现了,创建一个能够响应所有NSArray方法的集合代理对象返回(断点调试看到的是NSKeyValueArray对象)。如果没有,进入第三步
上面创建的代理对象随后将它收到的所有NSArray相关的消息(调用)转换成创建它的那个符合kvc规则的对象中countOf<Key>,objectIn<Key>AtIndex:<key>AtIndexs:的消息结合。如果原始的对象还实现了一个可选方法名字符合get<Key>:range:的范式,该代理对象在适当的时候也会使用改方法。实际上,这个代理对象和这个符合kvc规则的对象共同工作,允许下面的属性像一个NSArray一个呈现,即使那个属性并不是array。
3.如果简单的访问器方法和上述数组访问方法都没有,则开始搜寻三个名为countOf<Key>,enumeratorOf<Key>memberOf<Key:>的方法(与NSSet中的原始方法相对应)
如果三个方法都实现了,创造一个能够响应所有NSSet方法的集合代理对象返回(这里没做实验)。否则进入第4步
这个代理对象随后将收到的所有NSSet消息(调用)转换成创造它的那个对象中countOf<Key>,enumeratorOf<Key>memberOf<Key>:消息的组合。实际上,这个代理对象和这个符合kvc规则的对象共同工作,允许下面的属性像一个NSSet一个呈现,即使那个属性并不是set
4.如果上述的简单访问器方法和集合访问方法都没有找到,并且这个消息接收者的accessInstanceVariablesDirectly返回YES,那么按照_<key>,_is<Key>,<key>,或者is<Key>的顺序搜寻符合的实例变量。如果找到了,直接获取改实例变量进入第5步,如果没有,进入第6步。
5.如果返回的值是一个对象指针,直接返回
如果返回的是一个可以被包装成NSNumber的基础类型,包装成NSNumber返回
如果返回的是一个不能被包装成NSNumber的基础类型,转换成一个NSValue对象返回
6.如果上面所有的都失败了,调用valueForUndefinedKey:方法,这个方法默认会生成一个异常(crash在这方法里),不过NSObject的子类可以继承根据key做一些特定处理。

basic setter

setValue:forKey:

1.首先按顺序查找名为set<Key>:或者_set<Key>:方法,如果存在,将输入的值(或者解除封装,例如setvalue中传的一个NSNumber,set<Key>:中接收的是一个NSInteger)传入方法中调用。
2.如果简单的存取方法没找到,并且类的accessInstanceVariablesDirectly返回YES,按照_<key>,_is<Key>,<key>,或者is<Key>的名字顺序查找实例变量。如果找到了,直接设置变量值为输入值并且结束。
3.如果存取方法和实例变量都没找到,调用setValue:forUndefinedKey:方法,这个方法默认会生成一个异常,不果继承NSObject的子类可以根据key提供一些特定的处理

待续,后面还有为集合类set方法。

#参考
Key-Value Coding Programming Guide