iOS开发基础-KVC简单介绍
一、KVC介绍
键值编码(Key Value Coding,KVC):使开发者不必进行任何操作就可以进行属性的动态读写。
KVC操作方法由 NSKeyValueCoding 协议提供,而 NSObject 实现了这个协议,因此 ObjC 中几乎所有的对象都支持KVC操作,常用的操作方法如下:
1)动态设置: setValue:forKey: 用于简单路径, setValue:forKeyPath: 用于复合路径。如 Person 类有一个 Account 类型的属性,那么 Person.Account 就是一个复合属性。
2)动态读取: valueForKey: 、 valueForKeyPath: 。
补充:键值观察(Key Value Observer,KVO):监听某一个模型的属性,只要该模型属性的值发生变化就通知你。
二、代码实例1
新建 Command Line Tool 项目,并命名为 KVCDemo 。紧接着,为项目添加一个继承自 NSObject 类的 Person 类,为该新类添加名字和年龄属性,如下:
1 //Person.h 2 @property (nonatomic, copy) NSString *name; 3 @property (nonatomic, assign) int age;
在 Person 类的实现文件中重写 description 方法:
1 //Person.m 2 - (NSString *)description { 3 return [NSString stringWithFormat:@"<%@:%p>, {name:%@, age:%d}.", [self class], self, self.name, self.age]; 4 }
上述中 %p 指代指针。
在 main.m 文件中对 Person 进行简单的处理:
1 //main.m 2 int main(int argc, const char * argv[]) { 3 @autoreleasepool { 4 Person *p1 = [[Person alloc] init]; 5 [p1 setValue:@"WJQ" forKey:@"name"]; 6 [p1 setValue:@"23" forKey:@"age"]; 7 8 Person *p2 = [[Person alloc] init]; 9 [p2 setValue:@"LWX" forKey:@"name"]; 10 [p2 setValue:@"22" forKey:@"age"]; 11 NSLog(@"%@. %@.", p1, [p2 valueForKey:@"name"]); 12 } 13 return 0; 14 }
使用 setValue:forKey: 进行KVC操作时,系统会自动判断对象属性的类型并完成转换,如上例将 @"23" 转换为 23 。
输出为:
<Person:0x1006001c0>, {name:WJQ, age:23}.. LWX.
三、代码实例2
如何生成只包含 name 属性的数组,并打印出来?
在 main.m 文件中中导入 Person 类的头文件,并修改 main 函数的代码:
1 int main(int argc, const char * argv[]) { 2 @autoreleasepool { 3 Person *p1 = [[Person alloc] init]; 4 [p1 setValue:@"WJQ" forKey:@"name"]; 5 [p1 setValue:@"23" forKey:@"age"]; 6 7 Person *p2 = [[Person alloc] init]; 8 [p2 setValue:@"LWX" forKey:@"name"]; 9 [p2 setValue:@"22" forKey:@"age"]; 10 11 NSArray *persons = @[p1, p2]; //创建Person对象的数组 12 NSLog(@"%@", persons); 13 NSMutableArray *arrayM = [NSMutableArray array]; //用于存放各个Person的name 14 for (Person *p in persons) { 15 [arrayM addObject:[p valueForKeyPath:@"name"]]; 16 } 17 NSLog(@"%@", arrayM); 18 } 19 return 0; 20 }
输出为:
( "<Person:0x100208dc0>, {name:WJQ, age:23}.", "<Person:0x100209c80>, {name:LWX, age:22}." ) ( WJQ, LWX )
由于使用KVC按键值路径取值时,如果对象不包含指定的键值,会自动进入对象内部,查找对象的属性。在不改变输出的情况下,修改上述代码为:
1 int main(int argc, const char * argv[]) { 2 @autoreleasepool { 3 Person *p1 = [[Person alloc] init]; 4 [p1 setValue:@"WJQ" forKey:@"name"]; 5 [p1 setValue:@"23" forKey:@"age"]; 6 7 Person *p2 = [[Person alloc] init]; 8 [p2 setValue:@"LWX" forKey:@"name"]; 9 [p2 setValue:@"22" forKey:@"age"]; 10 11 NSArray *persons = @[p1, p2]; //创建Person对象的数组 12 NSLog(@"%@", persons); 13 NSMutableArray *arrayM = [NSMutableArray array]; //用于存放各个Person的name 14 [arrayM addObject:[persons valueForKeyPath:@"name"]]; 15 NSLog(@"%@", arrayM); 16 } 17 return 0; 18 }
三、代码实例3
演示根据键值路径取值,KVC机制会自动层层深入,并获取对应的键值。
为项目新建一个 Book 类继承自 NSObject ,添加 bookName 属性:
1 //Book.h 2 @property(nonatomic, copy) NSString *bookName;
修改 Book 类的 description 方法:
1 //Book.m 2 - (NSString *)description { 3 return [NSString stringWithFormat:@"<%@, %p>, {bookName:%@}", [self class], self, self.bookName]; 4 }
接着在 Person 类的头文件中导入 Book.h ,再添加一个 Book 类的对象属性,如下:
1 //Person.h 2 @property (nonatomic, strong) Book *book;
修改 Person 类的 description 方法,使其输出 book 属性:
1 //Person.m 2 - (NSString *)description { 3 return [NSString stringWithFormat:@"<%@:%p>, {name:%@, age:%d, book:%@}.", [self class], self, self.name, self.age, self.book]; 4 }
最后,修改 main 函数:
1 //main.m 2 int main(int argc, const char * argv[]) { 3 @autoreleasepool { 4 Person *p1 = [[Person alloc] init]; 5 [p1 setValue:@"WJQ" forKey:@"name"]; 6 [p1 setValue:@"23" forKey:@"age"]; 7 Book *b1 = [[Book alloc] init]; 8 b1.bookName = @"iPhone"; 9 p1.book = b1; 10 11 Person *p2 = [[Person alloc] init]; 12 [p2 setValue:@"LWX" forKey:@"name"]; 13 [p2 setValue:@"22" forKey:@"age"]; 14 Book *b2 = [[Book alloc] init]; 15 b2.bookName = @"iOS"; 16 p2.book = b2; 17 18 NSArray *persons = @[p1, p2]; //创建Person对象的数组 19 NSLog(@"%@", persons); 20 NSArray *arrayM = [persons valueForKeyPath:@"book.bookName"]; 21 NSLog(@"%@", arrayM); 22 } 23 return 0; 24 }
输出为:
( "<Person:0x1002095d0>, {name:WJQ, age:23, book:<Book, 0x10020c4c0>, {bookName:iPhone}}.", "<Person:0x10020c520>, {name:LWX, age:22, book:<Book, 0x10020c540>, {bookName:iOS}}." ) ( iPhone, iOS )
参考博客:ios开发UI篇—Kvc简单介绍