首先放上官方文档:
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueCoding_Protocol/index.html#//apple_ref/doc/uid/TP40003780
定义、解释:
KVC: Key Value Coding 键值编码
它是一种使用字符串标识符,间接访问对象属性的机制,而不是直接调用getter 和 setter方法。通常我们使用 valueForKey: 来替代getter 方法, setValue:forKey:来代替setter方法。
#import <Foundation/Foundation.h> @class Book; @interface Person : NSObject @property(nonatomic,copy)NSString *name; @property(nonatomic,assign) int age; @property(nonatomic,strong)Book *book; @end
用法1:赋值、取值
Person *p1=[[Person alloc] init]; //通常写法,不使用KVC p1.age = 23; p1.name = @"Jordan"; NSLog(@"%@",p1.hisName); //使用KVC [p1 setValue:@"Jordan" forKeyPath:@"name"];//赋值 [p1 setValue:@"23" forKeyPath:@"age"]; NSLog(@"%@",[hisValue valueForKey:@"name"]);//取值 Person *p2=[[Person alloc]init]; [p2 setValue:@"Mason" forKeyPath:@"name"]; [p2 setValue:@"22" forKeyPath:@"age"];
注意:使用KVC间接修改对象属性时,系统会自动判断对象属性的类型,并完成转换。如上的 “23”
用法2:取值 自动进入对象内部
比如只生成name的数组:
//建立一个存储person对象的数组 NSArray *persons=@[p1,p2]; NSMutableArray *arrayM=[NSMutableArray array]; //通常写法: // for (Person *p in persons) { // [arrayM addObject:[p valueForKeyPath:@"name"]]; // } //KVC写法: [arrayM addObject:[persons valueForKeyPath:@"name"]]; NSLog(@"%@",arrayM);
用法3:取值 层层深入:
Person *p1=[[Person alloc]init]; [p1 setValue:@"yangyong" forKeyPath:@"name"]; [p1 setValue:@"23" forKeyPath:@"age"]; Book *b1 = [[Book alloc] init]; b1.bookname = @"iPhone"; p1.book = b1; Person *p2=[[Person alloc]init]; [p2 setValue:@"heyun" forKeyPath:@"name"]; [p2 setValue:@"22" forKeyPath:@"age"]; Book *b2 = [[Book alloc] init]; b2.bookname = @"ios"; p2.book = b2; NSLog(@"%@%@", p1 , [p2 valueForKeyPath:@"name"]); //建立一个存储person对象的数组,并打印 NSArray *persons=@[p1,p2]; NSLog(@"%@",persons); NSArray *arrayM=[persons valueForKeyPath:@"book.bookname"]; NSLog(@"%@",arrayM);
总结 用法2 用法3
//只能获取对象属性的值 - (id)valueForKey:(NSString *)key; //可以获取对象属性的属性的值(推荐使用) - (id)valueForKeyPath:(NSString *)keyPath;
注意:KVC按照键值路径取值时,如果对象不包含指定的键值,会自动进入对象内部,层层深入,查找对象属性
另外:
模型--字典 互转
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues; //字典中的key 和对象属性要求一样 - (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]]); }
用法4:KVC的消息传递
通过调用valueForKey:给容器中每一个对象发送操作消息,并且结果会被保存在一个新的容器中返回,这样我们能很方便地利用一个容器对象创建另一个容器对象。另外,valueForKeyPath:还能实现多个消息的传递。一个例子:
NSArray *array = [NSArray arrayWithObject:@"10.11", @"20.22", nil]; NSArray *resultArray = [array valueForKeyPath:@"doubleValue.intValue"]; NSLog(@"%@", resultArray); /*打印结果 ( 10, 20 ) */
用法5:KVC容器操作
容器不仅仅能使用KVC方法实现对容器成员传递普通的操作消息,KVC还定义了特殊的一些常用操作,使用valueForKeyPath:结合操作符来使用,所定义的keyPath格式入下图所示
Left key path:如果有,则代表需要操作的对象路径(相对于调用者)
Collection operator:以"@"开头的操作符
Right key path:指定被操作的属性
常规操作符:
@avg、@count、@max、@min、@sum
(详见: http://nshipster.com/kvc-collection-operators/ )
对象操作符:
@distinctUnionOfObjects、@unionOfObjects
NSArray *values = [object valueForKeyPath:@"@unionOfObjects.value"];
@distinctUnionOfObjects操作符返回被操作对象指定属性的集合并做去重操作,而@unionOfObjects则允许重复。如果其中任何涉及的对象为nil,则抛出异常。
官网
取值:
- valueForKey: - valueForKeyPath: - dictionaryWithValuesForKeys: - valueForUndefinedKey: - mutableArrayValueForKey: - mutableArrayValueForKeyPath: - mutableSetValueForKey: - mutableSetValueForKeyPath: - mutableOrderedSetValueForKey: - mutableOrderedSetValueForKeyPath:
赋值:
- setValue:forKeyPath: - setValuesForKeysWithDictionary: - setNilValueForKey: - setValue:forKey: - setValue:forUndefinedKey:
参考摘抄如下:
http://www.cnblogs.com/wendingding/p/3751279.html
http://www.tuicool.com/articles/2aYfy2
http://www.tuicool.com/articles/eA36Vr2
http://my.oschina.net/wolx/blog/361762?fromerr=APuNmaxZ