KVC(KeyValueCoding)
(1)赋值类方法
- (void)setValue:(nullableid)value forKey:(NSString*)key;
- (void)setValue:(nullableid)value forKeyPath:(NSString*)keyPath;- (void)setValue:(nullableid)value forUndefinedKey:(NSString*)key;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
(2)取值类方法// 能取得私有成员变量的值
- (id)valueForKey:(NSString*)key;
- (id)valueForKeyPath:(NSString*)keyPath;
- (NSDictionary*)dictionaryWithValuesForKeys:(NSArray*)keys;
KVC 底层实现原理
假设key = @"name", 以下顺序执行,前一条件不成立,则执行下一个。
1. 判断是否有@"name"的set方法,有则赋值;
2. 判断有无_name(带下划线的)成员变量,有则赋值
3. 判断有无同名属性,有则赋值
4. 执行valueforUndefinedKey, setValue:forUndefinedKey:
KVC使用场景:
Person *p = [[Person alloc] init];
p.name = @"rose";
使用setValue:forKey:方法能够给属性赋值,等价于直接给属性赋值[p setValue:@"rose" forKey:@"name"];
这是常见用法;
但是,
如果私有成员变量,例如Person的.m文件中有一个_age, 该怎么赋值?
通过setValue:forKeyPath:方法。
Person *p = [[Person alloc]init];
[p setValue:@"Apple" forKeyPath:@"_age"];
假如Person中有一Dog类型的属性myDog,Dog是一个独立的类,Dog有个属性名name, 该怎么赋值?
同样通过setValue:forKeyPath:方法。
[p setValue:@"Apple" forKeyPath:@"myDog.name"];
字典转模型, setValuesForKeysWithDictionary:dict是关键
+(instancetype)videoWithDict:(NSDictionary*)dict{
JLVideo *videItem = [[JLVideo alloc] init];
[videItem setValuesForKeysWithDictionary:dict];returnvideItem;
}
取值, 获取值后存于新创建的NSDictionary
Person *p = [[Person alloc]init];
p.name = @"Angel";
p.age = @"12";
NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name",@"age"]];
NSLog(@"%@", dict);
把多个模型Dog放入数组中,想要提取数组模型Dog的属性name的值用于列表展示,该怎么做?
再次遍历模型,然后把对应的name的值存放于新数组中?
这一定是可行的,但是否过于麻烦?
能否简便一些?
Dog*d1 = [[Dogalloc]init];
d1.name =@"DoLin";
Dog*d2 = [[Dogalloc]init];
d2.name =@"Apple";
Dog*d3 = [[Dogalloc]init];
d3.name =@"Jucie";
NSArray*arrays =@[d1,d2,d3];
NSLog(@"我的数组名字结果---%@",[arrays valueForKeyPath:@"name"]);
arrays用于存放数组,当我想提取所有模型Dog的name值,直接调用[arrays valueForKeyPath:@"name"],即可得到一个新的只有名字的数组,是不是很便利?
如果Person类有一个数组,专门用于存放Dog, 想要提取Person数组中Dog的属性name的值用于列表展示,该怎么做?
大家首先想到的可能还是,再次遍历模型,然后把对应的name的值存放于新数组中?
我们换个新方式
Dog *d1 = [[Dog alloc]init];
d1.name =@"DoLin";
Dog*d2 = [[Dogalloc]init];
d2.name =@"Apple";
Dog*d3 = [[Dogalloc]init];
d3.name =@"Jucie";
Person *p = [[Person alloc]init];
p.dogArrays=@[d1,d2,d3];
NSLog(@"%@",[p valueForKeyPath:@"dogArrays.name"]);
讲多个Dog实例存放于Person类型的dogArrays数组里,调用[p valueForKeyPath:@"dogArrays.name"]即可得到相应的数据