1、什么是KVC
KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性
2、常见的API有
//赋值方法
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
//取值方法
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
forKey 和 forKeyPath 主要区别是路径区别如下
例:有2个类(Person和Dog) Person类有2个属性 name 和 dog Dog类 中也有一个name属性 如下:
@interface FCPerson : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,strong)Dog *dog;
@end
@interface Dog : NSObject
@property(nonatomic,strong)NSString *name;
@end
我们使用 setValue: forKey 对 Person name赋值
使用 和 setValue: forKeyPath对 Dog name赋值 如下所示:
FCPerson * person = [[FCPerson alloc]init];
person.dog = [[Dog alloc]init];
[person setValue:@"张三" forKey:@"name"];
[person setValue:@"小狗狗" forKeyPath:@"dog.name"];
NSLog(@"人名:%@---狗名:%@",person.name,person.dog.name);
最后打印的结果就是 人名:张三---狗名:小狗狗
setValue: forKey 只能对person类的属性赋值
如果想一层一层的对Dog类的属性进行赋值 就必须得用路径 setValue:forKeyPath 来赋值
如果直接使用 setValue: forKey 的方法对狗狗name赋值就会报错
所以:forKeyPath支持路径查找,forKey不支持
3、setValue:forKey:的原理如下图所示
setValue:forKey:的原理流程图.png如上图所示:
使用KVC给属性赋值 首先会去寻找 这个属性的setter方法 即setKey
如果没有找到setKey则直接找_setKey
如果找到了则直接赋值,如果没有找到则会查看
accessInstanceVariablesDirectly方法的返回值(默认返回YES)
如果返回NO(不允许直接访问成员变量)调用setValue:forUndefinedKey:
并抛出异常NSUnknownKeyException
如果返回YES 则直接去找(顺序查找,上一个查不到就继续查找下一个)
_Key、
_isKey、
key、
isKey
如果都没有找到 则直接调用setValue:forUndefinedKey:
并抛出异常NSUnknownKeyException
4、valueForKey:的原理如下图所示
valueForKey:的原理.png使用KVC获取属性的值 首先会去寻找 这个属性的getter方法即(顺序查找)
getKey、
key、
isKey
_key
如果找到则直接调用方法
如果找不到则直接查看
accessInstanceVariablesDirectly方法的返回值(默认返回YES)
如果返回NO 调用调用valueForUndefinedKey:
并抛出异常NSUnknownKeyException
如果返回YES 则直接去找(顺序查找,上一个查不到就继续查找下一个)
_Key、
_isKey、
key、
isKey
如果找到则直接取值
如果都没有找到 则直接调用valueForUndefinedKey:
并抛出异常NSUnknownKeyException
5、通过KVC修改属性会触发KVO么?
答:会触发KVO
如果实现的setter方法就比较好理解,使用KVO就会触发KVO方法
如果没有 setter方法 KVC就会主动调用willChangeVlaueForKey 和didChangeVlaueForKey方法
从而触发了 KVO监听方法。(相当于手动调用)
网友评论