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

重写这个方法为了实现两个目的:

  1. 模型中的属性和字典中的key不一致的情况,比如字典中有个id,我们需要把它赋值给uid属性;
  2. 字典中属性比模型的属性还多的情况。 如果出现以上两种情况而没有实现这个方法的话,程序就会崩溃。 这个方法的实现:
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    if ([key isEqualToString:@"id"]) {
        self.uid = value;
    }
}