您的位置:首页 > 移动开发 > Objective-C

Objective-C之KVC(键值编码)

2016-04-14 17:02 543 查看
IOS中Key-Value Coding (KVC)俗称键值编码,是一个非正式的协议,它提供一种机制来间接访问对象的属性。

直接访问对象是通过调用访问器的方法实现,而kvc不需要调用访问器的设置和获取方法,可以直接访问对象的属性。

KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,

常用的KVC操作方法如下:

1)对属性赋值(动态设置)

setValue:属性值 frKey:属性名(用于简单路径);

setValue:属性值 forKeyPath:属性路径(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性);kvc的一般用法:

setValue:属性值 forKey:属性名和valueForKey:属性名

- (void)viewDidLoad {
[super viewDidLoad];
[self test1];
}
#pragma mark --setValue:属性值 forKey:属性名
-(void)test1{
Person * person = [[Person alloc]init];
[person setValue:@"一个屌丝的程序员" forKey:@"name"];
NSString * name =[person valueForKeyPath:@"name"];
NSLog(@"%@",name);
}

输出结果:



2)对属性取值(动态读取):

valueForKey:属性名 (用于简单路径);

valueForKeyPath:属性名(用于复合路径);

setValue:属性值 forKeyPath:属性路径和valueForKeyPath:属性名(用于复合路径)

- (void)viewDidLoad {
[super viewDidLoad];
[self test2];
}
#pragma mark --setValue:属性值 forKeyPath:属性路径和valueForKeyPath:属性名(用于复合路径)
-(void)test2{
Person * person = [[Person alloc]init];
person.course = [[Course alloc]init];
[person setValue:@"Course是一个自定义类,course是student的属性" forKeyPath:@"course.CourseName"];
NSString * CourseName = [person valueForKeyPath:@"course.CourseName"];
NSLog(@"CourseName:%@",CourseName);
}
输出结果:



注意:

(1). key的值必须正确,如果拼写错误,会出现异常

(2). 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来

(3). 因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去

(4). NSArray/NSSet等都支持KVC

3)key值找不到时,异常处理

使用kvc时,如果代码中的key值不存在,会抛出异常,可以在类中通过重写它提供

- (void)setValue:(id)value forUndefinedKey:(NSString *)key</span>
当key不存在时,会自动调用上面的这个方法,可以在这个方法中进行处理

- (void)setValue:(id)value forUndefinedKey:(NSString *)key  {
if([key isEqualToString:@"id"])
self.userid = value;
}


4)KVC的字典转模型和模型转字典

1>字典转模型

当我们需要把json字符串反序列化成我们想要的对象 ,可以通过下面的方法

- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues

- (id)initWithDictionary:(NSDictionary *)dictionary {
self = [self init];
if (self){
[self setValuesForKeysWithDictionary:dictionary];
}
return self;
}

注意:字典中的key 和对象属性要求一样

2>模型转字典

- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;

NSDictionary *dic = [self.dataArray dictionaryWithValuesForKeys:@[@"name",@"age"]];
for (int i =0 ; i<dic.count; i++) {
NSLog(@"%@", [dic objectForKey:[dic allKeys][i]]);
}
5)总结

1)KVC需要把字符串属性名称转换后才能赋值,调用的set方法,性能消耗较高

2)KVC查找一个属性进行读取的一般顺序

1>动态设置属性,

优先考虑调用setA方法,如果没有该方法则优先考虑搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);

2>动态读取属性

优先考虑调用a方法(属性a的getter方法),如果没有搜索到则会优先搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的valueforUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: