6.7.实现字典转模型的自动转换
字典转模型的应用可以说是每个app必然会使用的场景,虽然实现的方式略有不同,但是原理都是一致的:遍历模型中所有属性,根据模型的属性名,去字典中查找key,取出对应的值,给模型的属性赋值。 像几个出名的开源库:JSONModel,MJExtension等都是通过这种方式实现的。
- 先实现最外层的属性转换:
// 创建对应模型对象
id objc = [[self alloc] init];
unsigned int count = 0;
// 1.获取成员属性数组
Ivar *ivarList = class_copyIvarList(self, &count);
// 2.遍历所有的成员属性名,一个一个去字典中取出对应的value给模型属性赋值
for (int i = 0; i OC 字符串
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 2.3 _成员属性名 => 字典key
NSString *key = [ivarName substringFromIndex:1];
// 2.4 去字典中取出对应value给模型属性赋值
id value = dict[key];
// 获取成员属性类型
NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
}
如果模型比较简单,只有NSString,NSNumber等,这样就可以搞定了。但是如果模型含有NSArray,或者NSDictionary等,那么我们还需要进行第二步转换。
内层数组,字典的转换
if ([value isKindOfClass:[NSDictionary class]] & ![ivarType containsString:@"NS"]) {
// 是字典对象,并且属性名对应类型是自定义类型
// 处理类型字符串 @"User" -> User
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
ivarType = [ivarType stringByReplacingOccurrencesOfString:@""" withString:@""];
// 自定义对象,并且值是字典
// value:user字典 -> User模型
// 获取模型(user)类对象
Class modalClass = NSClassFromString(ivarType);
// 字典转模型
if (modalClass) {
// 字典转模型 user
value = [modalClass objectWithDict:value];
}
}
if ([value isKindOfClass:[NSArray class]]) {
// 判断对应类有没有实现字典数组转模型数组的协议
if ([self respondsToSelector:@selector(arrayContainModelClass)]) {
// 转换成id类型,就能调用任何对象的方法
id idSelf = self;
// 获取数组中字典对应的模型
NSString *type = [idSelf arrayContainModelClass][key];
// 生成模型
Class classModel = NSClassFromString(type);
NSMutableArray *arrM = [NSMutableArray array];
// 遍历字典数组,生成模型数组
for (NSDictionary *dict in value) {
// 字典转模型
id model = [classModel objectWithDict:dict];
[arrM addObject:model];
}
// 把模型数组赋值给value
value = arrM;
}
}
我自己觉得系统自带的KVC模式字典转模型就挺好的,假设movie是一个模型对象,dict 是一个需要转化的 [movie setValuesForKeysWithDictionary:dict];这个是系统自带的字典转模型方法,个人感觉也还是挺好用的,不过使用这个方法的时候需要在模型里面再实现一个方法才行,
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
重写这个方法为了实现两个目的:
- 模型中的属性和字典中的key不一致的情况,比如字典中有个id,我们需要把它赋值给uid属性;
- 字典中属性比模型的属性还多的情况。 如果出现以上两种情况而没有实现这个方法的话,程序就会崩溃。 这个方法的实现:
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"id"]) {
self.uid = value;
}
}