KVC是如何通过key来存取属性的?这里是有一套规则的:
valueForKey:的查找规则
- 查找是否存在比较直接的访问方法。按照get<Key>, <key>, is<Key>, _<key>的顺序,如果找到就调用该方法并带着结果到步骤5,否则到第2步继续查找。
- 查找是否存在类似数组的方法。首先查找是否存在countOf<Key>方法,再查找是否有objectIn<Key>AtIndex:或<key>AtIndexes: 其中一个方法,如果找到,则会返回一个代理对象,该对象类似一个数组,数组含有的元素个数为第一个方法返回值,数组内的元素就是第二个方法返回值。在这种情况下不管属性是否是数组,kvc的返回值都是数组,实际类为NSKeyValueArray。
如果未找到上述方法,到第3步继续查找。 - 查找是否存在类似NSSet的方法。查找是否有countOf<Key>, enumeratorOf<Key>, 和 memberOf<Key>:三个方法,如果有则返回一个代理对象 ,该对象类似一个NSSet,和第2步类似。
如果未找到上述3个方法,到第4步继续查找。 - 直接查找实例变量。按照_<key>, _is<Key>, <key>, is<Key>的顺序,如果找到则直接获取变量并到步骤5,否则到步骤6。
- 如果得到的值是一个对象,直接返回结果。
如果得到一个可转为NSNumber非对象值,转为NSNumber并返回。
如果得到一个不可转为NSNumber的非对象值,如结构体,转为NSValue并返回。 - 未找到,调用valueForUndefinedKey:方法。
setValue:forKey:的查找规则
- 查找是否存在比较直接的访问方法。按照set<Key>:,_set<Key>的顺序,如果找到则调用该方法。否则到步骤2继续查找。
- 直接查找实例变量。按照_<key>, _is<Key>, <key>, is<Key>的顺序,如果找到直接设置变量。否则到步骤3。
- 未找到,调用setValue:forUndefinedKey:方法。
mutableArrayValueForKey:的查找规则
总是返回一个可变代理数组,遵循如下规则
- 查找insertObject:in<Key>AtIndex: removeObjectFrom<Key>AtIndex:,insert<Key>:atIndexes: 和 remove<Key>AtIndexes:这些方法。如果找到至少一个插入方法和至少一个删除方法,则返回一个代理对象,该对象对于可变数组的插入和删除的响应会转至上述方法。
- 没有找到上述可变数组的类似方法,则查找set<Key>:方法,返回一个代理对象,该对象对可变数组的插入和删除操作都会调用该方法。
- 前2步都未找到,直接查找实例变量,按照_<key> ,<key>的顺序,返回一个代理对象,该对象对可变数组的方法都会直接转发至实例变量,该变量最好是一个可变数组类,否则可能出现异常。
- 上述都未找到,依然返回一个可变代理数组,其接收到的可变数组的操作都会调用setValue:forUndefinedKey:方法。
值得注意的是,在满足上述步骤1或步骤2后,返回值会遵循valueForKey:的查找规则。
mutableOrderedSetValueForKey:和mutableSetValueForKey:查找规则
与mutableArrayValueForKey:类似,有兴趣的可查看官方文档或API说明