举例:
/**
kvc (key value coding) 和 对象
自动的做类型转换
为对象的name属性赋值
[p1 setValue:@"lisi" forKey:@"name"];
// 取出p1对象中 age属性的值
[p1 valueForKey:@"age"]
// 设置book对象的属性
[p1 setValue:@"随便" forKeyPath:@"book.bookName"];
*/
Person *p1 = [[Personalloc] init];
// p1.name = @"zhangsan";
// p1.age = 20;
[p1 setValue:@"lisi"forKey:@"name"];
// [p1 setValue:@"20" forKey:@"age"];
[p1 setValue:@"30"forKeyPath:@"age"];
// 实例化book对象
Book *b1 = [[Bookalloc] init];
b1.bookName = @"吃货大全";
p1.book = b1;
// 通过kvc修改book的名字
[p1 setValue:@"随便"forKeyPath:@"book.bookName"];
// NSLog(@"%@, %@ , bookName: %@",p1.name,[p1 valueForKey:@"age"],p1.book.bookName);
/**
kvc 和字典
字典里有的key值 --> p1对象中一定要由对应的属性名
字典里的key值 ,一定要和 对象中属性名保持一致
*/
NSDictionary *dict =@{@"name":@"wangwu",@"age":@"40"};
[p1 setValuesForKeysWithDictionary:dict];
// NSLog(@"%@, %@ , bookName: %@",p1.name,[p1 valueForKey:@"age"],p1.book.bookName);
/**
kvc 和数组
根据keyPath找到数组中对象的 name 属性, 并返回(数组)
NSArray *nameArray = [array valueForKeyPath:@"name"];
*/
Person *p2 = [[Personalloc] init];
p2.name = @"yellow Mokey";
Person *p3 = [[Personalloc] init];
p3.name = @"red dog";
Person *p4 = [[Personalloc] init];
p4.name =@"green chicken";
NSArray *array = @[p2,p3,p4];
// 把三个对象中的name 取出来
NSArray *nameArray = [array valueForKeyPath:@"name"];
NSLog(@"%@",nameArray);
}
==================
Key-Value-Coding:KVC顾名思义就是键值编码,通过[setValue:@"value" forKey:@"key"]来添加一组对象,编译器会把这行代码处理为SEL sel = sel_get_uid(@"setValue:forKey");
IMP method = objc_msg_lookup(site->isa,sel);
method(site, sel, @"value", @"key");这三步。
1.SEL数据类型就是编译器运行Objective-C里的方法的环境参数.
2.IMP数据类型其实就是一个编译器内部实现时候的函数指针,当Objective-C编译器去处理实现一个方法的时候,就会指向个IMP对象,这个对象是C语言表述的类型
3.所以当一个对象在调用SetValue的时候,首先根据方法名找到运行方法的时候所需要的环境参数,然后该对象会从自己的isa指针结合环境参数,找到具体的方法实现的接口,最后直接按查找到的具体的方法实现。
KVC是OC特有的,本质是在运行时动态的给对象发送setValue:forKey 消息,设置数值 -调用super.init 保证对象已经被创建完成 .当给对象发送setValue:forKey 消息时要判断对象是否存在key所对应的属性,直接赋值 如果没有就调用undefinedKey(默认崩溃,需要重写)
setValue:forKey的调用顺序首先会寻找set
a. setValue:forKey的搜索方式:
1. 首先搜索set
如果成员用@property,@synthsize处理,因为@synthsize告诉编译器自动生成set
注意:这里的
2. 上面的setter方法没有找到,如果类方法accessInstanceVariablesDirectly返回YES(注:这是NSKeyValueCodingCatogery中实现的类方法,默认实现为返回YES)。
那么按_
b. valueForKey:的搜索方式:
1. 首先按get
2. 上面的getter没有找到,查找countOf
如果countOf
3. 还没查到,那么查找countOf
如果这三个方法都找到,那么就返回一个可以响应NSSet所有方法的代理集合(collection proxy object)。发送给这个代理集合(collection proxy object)的NSSet消息方法,就会以countOf
4. 还是没查到,那么如果类方法accessInstanceVariablesDirectly返回YES,那么按_
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *,id> *)keyedValues;/这个方法用来字典转模型