转载

ios开发- 利用运行时(runtime)字典转模型

现在的ios开发中,我们通常会使用MVC模式。当我们拿到数据的时候,我们要把数据转成模型使用。

一般情况我们拿到的数据都是字典。这是我们就需要将字典转成模型对象了。

当对象的属性很少的时候,我们可以直接单独写出字典的键值,进行转换。

_属性 = dict["键"]

当对象的属性很多的时候,我们可以利用KVC批量设置。

setValuesForKeysWithDictionary:<#(NSDictionary *)#>

但是KVC批量转的时候,有个致命的缺点,就是当字典中的键,在对象属性中找不到对应的属性的时候

会报错。

这个时候,我们不妨反过来想一下。我们先获取到对象所有的属性名,然后加入到一个数组里面,然后再遍历,赋值。

在程序运行的时候,抓取对象的属性,这时候,要利用到运行时机制了,详情见下面的代码

 1 + (NSArray *)propertyList {  2       3     // 0. 判断是否存在关联对象,如果存在,直接返回  4     /**  5      1> 关联到的对象  6      2> 关联的属性 key  7        8      提示:在 OC 中,类本质上也是一个对象  9      */ 10     NSArray *pList = objc_getAssociatedObject(self, propertiesKey); 11     if (pList != nil) { 12         return pList; 13     } 14      15     // 1. 获取`类`的属性 16     /** 17      参数 18      1> 类 19      2> 属性的计数指针 20      */ 21     unsigned int count = 0; 22     // 返回值是所有属性的数组 objc_property_t 23     objc_property_t *list = class_copyPropertyList([self class], &count); 24      25     NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count]; 26      27     // 遍历数组 28     for (unsigned int i = 0; i < count; ++i) { 29         // 获取到属性 30         objc_property_t pty = list[i]; 31          32         // 获取属性的名称 33         const char *cname = property_getName(pty); 34          35         [arrayM addObject:[NSString stringWithUTF8String:cname]]; 36     } 37     NSLog(@"%@", arrayM); 38      39     // 释放属性数组 40     free(list); 41      42     // 设置关联对象 43     /** 44      1> 关联的对象 45      2> 关联对象的 key 46      3> 属性数值 47      4> 属性的持有方式 reatin, copy, assign 48      */ 49     objc_setAssociatedObject(self, propertiesKey, arrayM, OBJC_ASSOCIATION_COPY_NONATOMIC); 50      51     return arrayM.copy; 52 }

上面的代码中,有两段 判断是否有关联对象,和 设置关联对象的代码。是为了不重复执行此方法。

在获取到上面的属性数组之后,可以写字典转模型的方法了

 1 + (instancetype)objectWithDict:(NSDictionary *)dict {  2     id obj = [[self alloc] init];  3       4     //    [obj setValuesForKeysWithDictionary:dict];  5     NSArray *properties = [self propertyList];  6       7     // 遍历属性数组  8     for (NSString *key in properties) {  9         // 判断字典中是否包含这个key 10         if (dict[key] != nil) { 11             // 使用 KVC 设置数值 12             [obj setValue:dict[key] forKeyPath:key]; 13         } 14     } 15     16      17     return obj; 18 }
正文到此结束
Loading...