浅谈-KVC-的实现原理
简介
KVC
是 KeyValue Coding
的简称,俗称“键值编码”,遵循 NSKeyValueCoding
协议,它是一种可以直接通过字符串的名字 key
来访问类属性的机制,而不是通过调用 setter
、getter
方法访问。
对于 KVC
,Cocoa
自动放入和取出基本数据类型放入 NSNumber
或 NSValue
中,当使用 setValue:ForKey:
或者 valueForKey:
时,它自动将基本数据类型从这些对象中取出,仅 KVC
具有这种自动包装功能,常规方法调用和属性语法不具备该功能。
setValue:forKey
的实现方式:
以字符串的形式向对象发送消息,如果成员用 @property
,因为 @synthsize
告诉编译器自动生成 set<Key>:
格式的 setter
方法,所以这种情况下会直接搜索到。
首先查找以 set<Key>
命名的 setter
方法,如果没有找到查找以 _set<Key>
命名的方法;如果上面的方法没有找到,如果类方法 accessInstanceVariablesDirectly
返回 YES
,那么将在对象内部查找名为 _<key>
、_is<Key>
、<key>
、is<key>
的实例变量。如果找到则设置成员的值,如果没有查找调用 setValue:forUndefinedKey:
。
valueForKey:
的实现方式:
- 首先查找以
get<Key>
、<key>
、is<Key>
、_Key
的顺序查找方法,找到直接调用。 - 若是还没查到,那么如果类方法
accessInstanceVariablesDirectly
返回YES
,那么将在对象内部查找名为_<key>
、_is<Key>
、<key>
、is<key>
的实例变量。 - 再没查到,调用
valueForUndefinedKey:
。
综上,使用 KVC 访问属性的代价比直接使用存取方法性能开销要大。
值的正确性核查
KVC 提供属性值确认的 API,它可以用来检查 set 的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
实现核查方法,为如下格式:validate<Key>:error:
1 | - (BOOL)validateName:(id *)ioValue error:(NSError **)outError { |
调用核查方法:validateValue:forKey:error:
,默认实现会搜索 validate<Key>:error:
格式的核查方法,找到则调用,未找到默认返回 YES
。