现在的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_t23 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> 关联对象的 key46 3> 属性数值47 4> 属性的持有方式 reatin, copy, assign48 */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 // 判断字典中是否包含这个key10 if (dict[key] != nil) {11 // 使用 KVC 设置数值12 [obj setValue:dict[key] forKeyPath:key];13 }14 }15 16 17 return obj;18 }