现在的ios开发中,我们通常会使用MVC模式。当我们拿到数据的时候,我们要把数据转成模型使用。
一般情况我们拿到的数据都是字典。这是我们就需要将字典转成模型对象了。
当对象的属性很少的时候,我们可以直接单独写出字典的键值,进行转换。
_属性 = dict["键"]
当对象的属性很多的时候,我们可以利用KVC批量设置。
setValuesForKeysWithDictionary:<#(NSDictionary *)#>
但是KVC批量转的时候,有个致命的缺点,就是当字典中的键,在对象属性中找不到对应的属性的时候
会报错。
这个时候,我们不妨反过来想一下。我们先获取到对象所有的属性名,然后加入到一个数组里面,然后再遍历,赋值。
在程序运行的时候,抓取对象的属性,这时候,要利用到运行时机制了,详情见下面的代码
+ (NSArray *)propertyList {
//0. 判断是否存在关联对象,如果存在,直接返回
/**
1> 关联到的对象
2> 关联的属性 key
提示:在 OC 中,类本质上也是一个对象
*/
NSArray *pList =objc_getAssociatedObject(self, propertiesKey);
if(pList !=nil) {
return pList;
}
//1. 获取`类`的属性
/**
参数
1> 类
2> 属性的计数指针
*/
unsigned int count =0;
//返回值是所有属性的数组 objc_property_t
objc_property_t *list = class_copyPropertyList([self class], &count);
NSMutableArray *arrayM =[NSMutableArray arrayWithCapacity:count];
//遍历数组
for(unsigned int i =0; i < count; ++i) {
//获取到属性
objc_property_t pty =list[i];
//获取属性的名称
const char *cname =property_getName(pty);
[arrayM addObject:[NSString stringWithUTF8String:cname]];
}
NSLog(@"%@", arrayM);
//释放属性数组
free(list);
//设置关联对象
/**
1> 关联的对象
2> 关联对象的 key
3> 属性数值
4> 属性的持有方式 retain, copy, assign
*/
objc_setAssociatedObject(self,propertiesKey,arrayM,OBJC_ASSOCIATION_COPY_NONATOMIC);
return arrayM.copy;
}
上面的代码中,有两段 判断是否有关联对象,和 设置关联对象的代码。是为了不重复执行此方法。
在获取到上面的属性数组之后,可以写字典转模型的方法了
+ (instancetype)objectWithDict:(NSDictionary *)dict {
id obj =[[self alloc] init];
// [obj setValuesForKeysWithDictionary:dict];
NSArray *properties =[self propertyList];
//遍历属性数组
for(NSString *key in properties) {
//判断字典中是否包含这个key
if(dict[key] !=nil) {
//使用 KVC 设置数值
[obj setValue:dict[key] forKeyPath:key];
}
}
return obj;
}