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:属性名
输出结果:
2)对属性取值(动态读取):
valueForKey:属性名 (用于简单路径);
valueForKeyPath:属性名(用于复合路径);
setValue:属性值 forKeyPath:属性路径和valueForKeyPath:属性名(用于复合路径)
注意:
(1). key的值必须正确,如果拼写错误,会出现异常
(2). 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来
(3). 因为类key反复嵌套,所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去
(4). NSArray/NSSet等都支持KVC
3)key值找不到时,异常处理
使用kvc时,如果代码中的key值不存在,会抛出异常,可以在类中通过重写它提供
4)KVC的字典转模型和模型转字典
1>字典转模型
当我们需要把json字符串反序列化成我们想要的对象 ,可以通过下面的方法
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues
注意:字典中的key 和对象属性要求一样
2>模型转字典
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
1)KVC需要把字符串属性名称转换后才能赋值,调用的set方法,性能消耗较高
2)KVC查找一个属性进行读取的一般顺序
1>动态设置属性,
优先考虑调用setA方法,如果没有该方法则优先考虑搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);
2>动态读取属性
优先考虑调用a方法(属性a的getter方法),如果没有搜索到则会优先搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的valueforUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);
直接访问对象是通过调用访问器的方法实现,而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:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);
相关文章推荐
- oc开发笔记2 AUGraph 完成同时录音与播放
- 关于Objective - C
- Block初探
- 学习ios【1】Objective-C 基本语法
- JS如何区分Object与Aarry的六种方法
- Objective—C中的排序及Compare陷阱
- NSDictionaryValueForKey与ObjectForKey区别
- 禅与 Objective-C 编程艺术
- Objective-C Runtime之着魔的UIAlertView
- Objective - C CALayer的简介
- Objective - C CAAnimation动画
- Objective-C Runtime之着魔的UIAlertView
- OC学习日记Day3:数据在内存的储存形式,CPU查找内存数据
- Android Intent传递List<Object>数据
- 关于CGImageRef
- 【JavaScript】Object.prototype.toString.call()进行类型判断
- 对于AttributeError: 'Flask' object has no attribute 'cli'的解决办法
- Objective-C的属性(property)解析:
- SQL sever 中系统表sys.objects的作用与字段含义
- warning: Could not resolve external type c:objc(cs