一、KVC
KVC就是key-Value-coding,即键值编码,通常情况给某一个对象进行赋值。但是通常赋值操作直接使用点语法即可,简单方便,例如:
Person *p = [[Person alloc]init];
p.name = @"张三";
p.age = 20;`
我们也可以通过KVC给p赋值,代码如下,因为setValue这里的值是id类型的,所以将整数包装成一个对象,
[p setValue:@"张三" forKey:@"name"];
[p setValue:@20 forKey:@"age"];
我们为什么不用点语法这样简单的操作进行赋值操作,而要使用KVC呢?
比如Person类有一个私有属性,并且对外提供一个输出私有属性值的接口,例如:
#import "Person.h"
@impletation Person
{
NSInteger _height;
}
- (void)logHeight
{
NSLog(@"%ld",_height);
}
这样的情况,我们在外部是无法直接给p设置身高的,外部无法访问到私有属性,但是有了KVC就不一样了。
[p setValue:@170 forKey:@"height"];
[p logHeight];
我们在外部通过KVC直接对私有属性赋值,打印如下:
2016-11-03 17:42:27.174 KVODemo[1246:41973] 170
除了[p setValue:@170 forKey:@"height"]
这个方法外,还有一个方法可以对私有属性赋值:
[p setValue:@170 forKeyPath:@"height"]
。
这两个方法对于普通的属性是没有区别的,都可以用,但是对一些特殊的属性就有区别了。
比如说这个类又个属性是狗,狗又有属性体重:
p.dog = [[Dog alloc] init];
[p setValue:@200 forKey:@"dog.weight"];
如果我们直接这样设置是会报错说找不到dog.weight,而在storyboard中,我们拖控件连线错误的时候报错也说找不到什么key,说明storyboard在赋值的时候也是通过KVC来操作的。
但是,我们换另外一种方法,不会报错,而且可以打印出狗的体重。
[p setValue:@200 forKeyPath:@"dog.weight"];
说明forKeyPath
是包含了forKey
这个方法的功能的,甚至 forKeyPath
方法还有它自己的高级功能,它会先去找有没有dog这个key,然后去找有没有weight这个属性。所以在使用KVC的时候,最好使用 forKeyPath
这个方法。
最后还有一点,代码如下:
[p setValue:@170 forKey:@"height"];
我们传入的字符串key是height
,但是定义的属性是 _heigth
,但是通过kvc还是可以给 _height
属性赋到值。说明对某一属性进行赋值操作,可以不用加下划线,而且它的查找规则应该是:先查找与写入字符转相同的成员变量,如果找不到就找以下划线开头的成员变量。
KVC除了访问私有变量的作用外,还可以用于字典转模型。在Person
类对外提供一个接口,将转模型的工作放在模型中进行
- (instancetype)initWithDict:(NSDictionary *)dict
{
if(self = [super init]) {
[self setValueForKeysWithDictionary:dict];
}
return self;
}
kvc用法总结
* 1.在外部对私有变量进行赋值
* 2.字典转模型
注意
* 1.字典转模型的时候,字典的某一个key一定要在模型中有对应的属性
* 2.如果模型中包含了另外的模型对象,是不能直接转化成功的。
* 3.通过kvc转化模型中的模型,也是不能直接转换成功的。
既然可以通过kvc赋值,也可以通过它取值:
NSLog(@"name=%@",[p valueForKey:@"name"]);
NSLog(@"dogWeight=%@",[p valueForKeyPath:@"p.dog"]);