美文网首页
iOS --- KVC底层原理及应用

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

作者: BabyNeedCare | 来源:发表于2019-06-24 11:05 被阅读0次

    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底层原理及应用

          本文链接:https://www.haomeiwen.com/subject/hwqnqctx.html