各种姿势玩转KVC

本文详细介绍在iOS开发中对KVC使用的一些心得体会,希望对阅读者有帮助,如有疏漏之处望指正,谢列位看官。


1.利用KVC给模型属性赋值用  [model   setValuesForKeysWithDictionary:dict] 

  1. + (instancetype)statusWithDict:(NSDictionary *)dict {
  2.    id obj = [[self alloc] init];
  3.    
  4.    [obj setValuesForKeysWithDictionary:dict];
  5.    
  6.    return obj;
  7. } 

  

  (1)这个方法的底层通过调用  enumerateKeysAndObjectsUsingBlock:   一个个地取出字典当中的key,判

     断调用对象model  有没有setKey(就是看调用对象有没有这个属性的set方法)通过respondsToSelector:

     判断,如果有,直接在set方法中将value赋值给属性

  (2)如果没有,看有没有带下划线的成员变量  _key,如果有,直接进行赋值

  (3)如果没有,看有没有不带下划线的成员变量  key,如果有,直接进行赋值

  (4)都没有,表示在对象当中没有找到对应的成员变量,会报错


2.两个使用前提:

   (1)字典中的键名必须要和模型中的属性名都保持一致

   (2)保证模型中的属性个数不能少于字典中的键值对的个数,如果字典中的键值对个数多于模型的属性个数,重写setValueforUndefinedKey:


3.使用场景

   (1)赋值  setValue: forKeyPath:  

    相比 setValue: forKey:  可以通过路径取值,赋值

  1. Person *p = [[Person alloc] init];
  2.    Dog *dog = [[Dog alloc] init];
  3.    p.dog = dog;
  4.    p.name = @"张三";
  5.    p.age = 18;
  6.    NSLog(@"%@-----%d",p.name, p.age);
  7.    // 1.kvc的赋值
  8.    [p setValue:@"李四" forKeyPath:@"name"];
  9.    [p setValue:@"20" forKeyPath:@"age"];
  10.    [p setValue:@"旺财" forKeyPath:@"dog.name"];
  11.    NSLog(@"%@-----%d------%@",p.name, p.age,dog.name);

  (2)取值   valueForKeyPath:  

  1. // 2.kvc的取值     能够一次拿到所有对象的同一个属性
  2.    Person *p1 = [[Person alloc] init];
  3.    p1.name = @"a";
  4.    p1.age = 18;
  5.    Person *p2 = [[Person alloc] init];
  6.    p2.name = @"b";
  7.    p2.age = 19;
  8.    Person *p3 = [[Person alloc] init];
  9.    p3.name = @"c";
  10.    p3.age = 20;
  11.    NSArray *persons = @[p1, p2, p3]; NSLog(@"%@",[persons valueForKeyPath:@"p1.age"]);
  12.    //    NSLog(@"%@-----%d",[p valueForKeyPath:@"name"],[[p valueForKeyPath:@"age"] intValue]);

 (3)模型转字典   dictionaryWithValuesForKeys:

  1. // 3.模型转字典
  2.    Person *p = [[Person alloc] init];
  3.    p.name = @"tom";
  4.    p.age = 18;
  5.    NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name",@"age"]];
  6.    NSLog(@"%@",dict);

    属性较多的处理方式:

  1.  #import <objc/runtime.h>                         运行时的框架
  2. //把自定义对象的数组,所有的对象都转换成字典
  3.    NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:2];
  4.    for (HMVideo *video in array)
  5.    {
  6.        //  以下为改良代码***********************************
  7.        unsigned int iCount = 0;
  8. //        unsigned int pCount = 0;
  9.        
  10.        Ivar *iList = class_copyIvarList([HMVideo class],  &iCount);        
  11.        NSLog(@"成员变量数量%u", iCount);
  12. //        NSLog(@"属性数量%u", pCount);
  13.        
  14.        NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:iCount];
  15.        
  16.        // 遍历数组
  17.        for (int i = 0; i < iCount; i++)
  18.        {
  19.            // 成员变量名称
  20.            const char *name = ivar_getName(iList[i]);
  21.            
  22.            [arrayM addObject:[NSString stringWithUTF8String:name]];
  23.        }
  24.        NSLog(@"------------>%@", arrayM);
  25.        
  26.        // 释放对象
  27.        free(iList);
  28.        
  29.        NSDictionary *dic = [video dictionaryWithValuesForKeys:arrayM];
  30.        [mArray addObject:dic];
  31.    }
  32.    
  33.    NSData *data = [NSJSONSerialization dataWithJSONObject:mArray options:0 error:NULL];
  34.    [self postJSON:data];


(4)字典转模型   setValuesForKeysWithDictionary:


4.如果解析网络数据之后的字典中有一部分键值模型中不需要,可以重写

- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;


5.解析之后的字典中有键值为id ,可以使用KVC进行赋值


6.解析之后的字典中的键值有int等数据类型关键字处理方式:

  1. -(void)setValue:(id)value forUndefinedKey:(NSString *)key
  2. {
  3.    if ([key isEqualToString:@"int"]) {
  4.        self.intxxx = value;
  5.    }
  6. }


7.KVC的方法是  NSObject的方法  写在(NSKeyValueCoding)分类中


8.多重模型的嵌套

  1. - (void)setValue:(id)value forKey:(NSString *)key {
  2.    // 判断 key 是否是 user
  3.    if ([key isEqualToString:@"user"]) {
  4.        self.user = [HMUser userWithDict:value];
  5.        
  6.        return;
  7.    }
  8.    // 判断 key 是否是 retweeted_status
  9.    if ([key isEqualToString:@"retweeted_status"]) {
  10.        self.retweeted_status = [HMStatus statusWithDict:value];
  11.        
  12.        return;
  13.    }
  14.    // 判断 key 是否是 pic_urls
  15.    if ([key isEqualToString:@"pic_urls"]) {
  16.        
  17.        NSMutableArray *urls = [NSMutableArray array];
  18.        
  19.        // 遍历数组,生成 url 数组
  20.        for (NSDictionary *dict in value) {
  21.            [urls addObject:[NSURL URLWithString:dict[@"thumbnail_pic"]]];
  22.        }
  23.        
  24.        self.pic_urls = urls.copy;
  25.        
  26.        return;
  27.    }
  28.    
  29. !!![super setValue:value forKey:key];
  30. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值