iOS --- KVC底层原理及应用

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"]即可得到相应的数据

你可能感兴趣的:(iOS --- KVC底层原理及应用)