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 }