一、KVC深入理解
a. 概念:
KVC:指的是 key valued coding 键值编码。
b. 赋值:
使用KVC间接修改对象属性时,系统会自动判断对象属性的类型,并完成转换。
c. 取值:
KVC按照键值路径取值时,如果对象不包含指定的键值,会自动进入对象内部层层深入,获取对应的键值。
d. 注意:
KVC是一种间接修改/读取对象属性的一种方式,在使用时需要注意,键值名称在对象属性中必须存在,否则会崩溃!
e. 操作方法:
KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:
1> 动态设置:
setValue:属性值 forKey:属性名
setValue:属性值 forKeyPath:属性路径(常用于复合路径)
2> 动态读取:
valueForKey:属性名
valueForKeyPath:属性路径(常用于复合路径)
f. 具体实现过程:
KVC 使用起来比较简单,假设现在要利用 KVC 对属性 a 进行读取:
1> 赋值过程:
如果是动态设置属性,则优先考虑调用 setA 方法,如果没有该方法则优先考虑搜索成员变量 _a,如果仍然不存在则搜索成员变量 a,如果最后仍然没搜索到则会调用这个类的
setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);
2> 取值过程:
如果是动态读取属性,则优先考虑调用 a 方法(属性 a 的getter方法),如果没有搜索到则会优先搜索成员变量 _a,如果仍然不存在则搜索成员变量 a,如果最后仍然没搜索到
则会调用这个类的 valueforUndefinedKey: 方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取)。
二、KVC具体使用示例及打印日志结果
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface People : NSObject
{
@private
int _age;
double height;
}
@property (nonatomic,copy) NSString *name;
@property (nonatomic,strong) Dog *dog;
@end
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@property (nonatomic,copy) NSString *color;
@end
#import "ViewController.h"
#import "People.h"
#import "Dog.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
People *p1 = [[People alloc] init];
Dog *dog = [[Dog alloc] init];
p1.dog = dog;
p1.name = @"huawuque";
[p1 setValue:@18 forKey:@"age"];
[p1 setValue:@1.8 forKey:@"height"];
[p1 setValue:@"yellow" forKeyPath:@"dog.color"];
NSLog(@"name: %@",p1.name);
NSLog(@"age: %d",[[p1 valueForKeyPath:@"age"] intValue]);
NSLog(@"height: %.2f",[[p1 valueForKeyPath:@"height"] doubleValue]);
NSLog(@"color: %@",[p1 valueForKeyPath:@"dog.color"]);
}
@end
// 模型属性作为key值转成字典,但是这里好像不能传入keyPath,会崩溃
NSDictionary *dict = [p2 dictionaryWithValuesForKeys:@[@"age",@"height",@"name"]];
NSLog(@"dict:%@",dict);
NSArray *persons = @[p1,p2];
// 一次性取出 persons 数组里面所有的 person 对象的属性 name 的值存放于数组中
NSArray *names = [persons valueForKeyPath:@"name"];
NSLog(@"names:%@",names);
People *p3 = [[People alloc] init];
NSDictionary *dic = @{@"name":@"yaoyue",@"age":@25,@"height":@16};
// 字典转模型
[p3 setValuesForKeysWithDictionary:dic];
// 为了跟踪 People 类的输出日志,重写了 People 类的 description 方法
NSLog(@"p3: %@",p3);