kvc原理

kvc就是key value coding,在Foundation框架中有一个类叫NSKeyValueCoding, 在这里有关于kvc的一切。

  • 关于kvc的使用,常用的就是这四个方法:
- (nullable id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
  • 以及一些其他不常用的方法:
- (nullable id)valueForUndefinedKey:(NSString *)key;
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
- (void)setNilValueForKey:(NSString *)key;
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
  • 使用方法没什么可说的,说说kvc的底层实现原理:
    这里有一个关键的属性:
@property (class, readonly) BOOL accessInstanceVariablesDirectly;

这个属性字面翻译下就是:能否直接访问实例变量?
这个属性的注释:

 Return YES if -valueForKey:, -setValue:forKey:, -
mutableArrayValueForKey:, -storedValueForKey:,
 -takeStoredValue:forKey:, and -takeValue:forKey:
 may directly manipulate instance variables 
when sent to instances of the receiving class, NO otherwise. 
The default implementation of this property returns YES.

很easy的英文,大概翻译一下:

如果一个对象想通过调用这些方法-valueForKey:, -setValue:forKey:, -
mutableArrayValueForKey:, -storedValueForKey:,
 -takeStoredValue:forKey:, and -takeValue:forKey:来访问自身的实例变量,则返回yes,反之no
默认返回yes

当一个对象object调用setValue:forKey:or setValue:forKeyPath:的时候,首先会查找这个key的set方法:-(void)setKey:还有另外一个加下划线_-(void)_setKey:,找到两个方法重的任一则直接调取完成赋值。如果找不到则去查询accessInstanceVariablesDirectly方法是否返回yes, 如果是no的话,就看是否实现了- (void)setValue:forUndefinedKey:,如果没实现,则crash报错Terminating app due to uncaught exception NSUnknownKeyException; 如果accessInstanceVariablesDirectly返回yes, 则可以访问实例变量了,依次查找key_keyisKey_isKey是否存在,如果有的话,直接完成赋值,如果没有则走到了- (void)setValue:forUndefinedKey:


当一个对象object调用valueForKey:or valueForKeyPath:的时候,首先会查找这个key的get方法:getKey:-_getKey:_keykey,找到两个方法重的任一则直接调取完成读取。如果找不到则去查询accessInstanceVariablesDirectly方法是否返回yes, 如果是no的话,就看是否实现了- valueForUndefinedKey:,如果没实现,则crash报错Terminating app due to uncaught exception NSUnknownKeyException; 如果accessInstanceVariablesDirectly返回yes, 则可以访问实例变量了,依次查找key_keyisKey_isKey是否存在,如果有的话,直接完成取值,如果没有则走到了- valueForUndefinedKey:,逻辑跟以上大同小异。


简单的画个图演示下(只画一个):

kvc原理_第1张图片


你可能感兴趣的:(kvc原理)