Objective-C 中,KVC(Key-Value Coding)
是一种使用字符串作为键值来间接访问对象属性的机制。在 NSObject
类中有如下两个方法:
1 | - (nullable id)valueForKey:(NSString *)key; |
有时候为了方便我们会使用 -valueForKey:
替代属性的 getter
方法,用 -setValue:forKey:
替代 setter
方法。下面根据 <Foundation/NSKeyValueCoding.h>
头文件中的描述,我们来看一下 setValue:forKey:
方法的内部实现以及使用注意事项。
(1) 当调用一个对象的 -setValue:forKey:
方法时,首先会去该对象(接收者)对应的类中查找与 key
相匹配的 setter
方法(-set<Key>
),如果找到了相应的方法,就检查方法的参数的类型。如果 setter
方法的参数是一个对象指针类型,就会直接调用上面匹配到的 setter
方法,并传入 value
作为参数。如果 setter
方法参数的类型不是一个对象指针类型,如基本类型等,但 value
值为 nil
,就会调用 -setNilValueForKey:
方法,该方法的默认实现是抛出一个 NSInvalidArgumentException
异常,我们一般需要重写它。
(2) 当对象(接收者)没有找到 key
对应的 setter
方法时,如果接收者的类属性 +accessInstanceVariablesDirectly
返回 YES
(默认值),就查找这个接收者是否存在实例变量的名称与 _<key>
, _is<Key>
, <key>
, is<Key>
(按照这个顺序)相匹配(例如,key
为 name
,那么对象中如果存在名为 _name
, _isName
, name
, isName
中的其中一个实例变量,就算匹配上了),如果找到这样一个实例变量,就使用 value
对其进行赋值。
(3) 当上述两个条件都不满足时,就会调用 -setValue:forUndefinedKey:
方法,该方法的默认实现是抛出一个 NSUndefinedKeyException
异常,我们一般需要重写这个方法以处理该异常。
另外,valueForKey:
方法的内部实现也与之类似,详见 NSKeyValueCoding.h
中的说明,这里不再赘述。
综上,当我们使用 setValue:forKey:
方法时,如果对象中 key
对应的属性或实例变量不存在,或者对于非对象指针类型传入的 value
值为 nil
时,都会抛出异常,如果我们没有进行处理,程序就会崩溃,所以我们一般会通过 category
的方式重写 NSObject
的 -setNilValueForKey:
和 -setValue:forUndefinedKey:
以及 valueForUndefinedKey
方法,如下图所示:
测试例子:
输出结果:
参考