1、简介
1> KVC,Key Value Coding,键值编码
2> 允许以字符串的形式间接的操作对象的属性
3> 其他操作属性的方式:set方法、get方法、点语法
2、常用方法
3、KVC底层setValue:属性值 forKey:属性名 为指定属性设置值
valueForKey:属性名 获取指定属性的值
关键代码
@property (nonatomic, copy) NSString *name; @property (nonatomic, copy) NSString *number; @property (nonatomic, copy) NSDate *birthday; // 使用KVC的方式为属性赋值 // 强调:属性值可以是任何类型的对象 [man setValue:@"华安" forKey:@"name"]; [man setValue:@"9527" forKey:@"number"]; [man setValue:[[NSDate alloc]init] forKey:@"birthday"];
1、setValue:属性值 forKey:@"name"
1> 调用setName:方法,通过set方法完成设置
2> 对_name成员变量赋值,与其定义的位置和修饰符无关,都是对_name赋值
3> 对name成员变量赋值,与其定义的位置和修饰符无关,都是对name赋值
4> 执行该对象的setValue: forUndefinedKey:方法
2、valueForKey:@"name"
1> 调用name方法,通过get方法获取返回值
2> 返回_name成员变量的值,与其定义的位置和修饰符无关,都是返回_name的值
3> 返回name成员变量的值,与其定义的位置和修饰符无关,都是返回name的值
4> 执行该对象的valueforUndefinedKey:方法
4、处理不存在的key
[p setValue:@"Stephen" forKey:@"name"]; // *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Person 0x10010e2f0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.' // 原因:没有name这个key // 解决:重写 setValue: forUndefinedKey:这个方法
5、处理nil值
// 使用KVC的方式为属性赋值 // 强调:KVC中,int类型的属性不能接受nil值 [goods setValue:nil forKey:@"name"]; [goods setValue:nil forKeyPath:@"price"]; // int类型的属性值为nil时(基本类型的属性值为nil时都会如此) // 出现的错误 // *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<Product 0x10010e2e0> setNilValueForKey]: could not set nil as the value for the key price.' // 错误的原因 // 不能把price这个key的值设置为nil,而这里设置成了nil // 分析该错误 // 该错误实际上是由setNilValueForKey:方法产生的,即如果设置某个属性值为nil,但是该属性却不接受nil值时,程序自动执行该对象的setNilValueForKey:方法 // 解决该错误 // 重写该对象的 setNilValueForKey: 方法 // 使用KVC的方式为属性赋值 // 强调:KVC中,int类型的属性不能接受nil值 [goods setValue:nil forKey:@"name"]; [goods setValue:nil forKeyPath:@"price"]; // int类型的属性值为nil时(基本类型的属性值为nil时都会如此) // 出现的错误 // *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<Product 0x10010e2e0> setNilValueForKey]: could not set nil as the value for the key price.' // 错误的原因 // 不能把price这个key的值设置为nil,而这里设置成了nil // 分析该错误 // 该错误实际上是由setNilValueForKey:方法产生的,即如果设置某个属性值为nil,但是该属性却不接受nil值时,程序自动执行该对象的setNilValueForKey:方法 // 解决该错误 // 重写该对象的 setNilValueForKey: 方法 - (void)setNilValueForKey:(NSString *)key { if ([key isEqualToString:@"price"]) { // price属性 price = 0; // 说明:如果没有@synthesize price;这段代码,则此处使用price = 0; } else { [super setNilValueForKey:key]; // 回调父类的setNilValueForKey:方法,即执行默认行为 } }
6、KVC的复合属性keyPath
1> 复合属性的概念
假设类型A、B
1.如果A对象包含B类型的属性b,而B对象又包含b1、b2属性
2.那么b.b1、b.b2可称为复合属性
2> 常用方法
setValue:属性值 forKeyPath:属性名 设置复合属性的属性值
valueForKeyPath:属性名 获取复合属性的属性值
3> 关键代码
// Shopping.h // 商品 @property (strong, nonatomic) Computer *computer; // 数量 @property (assign, nonatomic) int amount; // Shopping.m - (int)totalPrice { return computer.price * amount; } // Computer.h @property (copy, nonatomic) NSString *name; @property (assign, nonatomic) int price; // main.m // 创建对象 Shopping *shop = [[Shopping alloc]init]; // KVC赋值 [shop setValue:@"12" forKey:@"amount"]; [shop setValue:[[Computer alloc]init] forKey:@"computer"]; // key路径设置复合属性的值 [shop setValue:@"Mac Pro" forKeyPath:@"computer.name"]; // key路径获取符合属性的值 [shop setValue:[NSNumber numberWithInt:20] forKeyPath:@"computer.price"]; NSLog(@"\n清单为:%@个%@\n总价为:%@", [shop valueForKey:@"amount"], [shop valueForKeyPath:@"computer.name"], [shop valueForKey:@"totalPrice"] );