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 }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。