• Runtime----字典转模型


    1 字典key与模型属性不匹配(模型属性数量>字典键值对数)

    #import "NSObject+Model.h"
    #import <objc/message.h>
    
    @implementation NSObject (Model)//获取类中的所有成员变量
    //class_copyIvarList(__unsafe_unretained Class cls, unsigned int *outCount)
    
    // Runtime:根据模型中属性,去字典中取出对应的value给模型属性赋值
    // 思路:遍历模型中所有属性->使用运行时
    + (instancetype)modelWithDict:(NSDictionary *)dict
    {
        // 1.创建对应的对象
        id objc = [[self alloc] init];
        
        // 2.利用runtime给对象中的属性赋值
        /**
         class_copyIvarList: 获取类中的所有成员变量
         Ivar:成员变量,以下划线开头
         第一个参数:表示获取哪个类中的成员变量
         第二个参数:表示这个类有多少成员变量,传入一个Int变量地址,会自动给这个变量赋值
         返回值Ivar *:指的是一个ivar数组,会把所有成员属性放在一个数组中,通过返回的数组就能全部获取到。
         count: 成员变量个数
         */
        unsigned int count = 0;
        // 获取类中的所有成员变量
        Ivar *ivarList = class_copyIvarList(self, &count);
    
        // 遍历所有成员变量
        for (int i = 0; i < count; i++) {
            // 根据角标,从数组取出对应的成员变量
            Ivar ivar = ivarList[i];
            
            // 获取成员变量名字
            NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            // 处理成员变量名->字典中的key(去掉 _ ,从第一个角标开始截取)
            NSString *key = [ivarName substringFromIndex:1];
            
            // 根据成员属性名去字典中查找对应的value
            id value = dict[key];
            
            //【如果模型属性数量大于字典键值对数理,模型属性会被赋值为nil】
            // 而报错 (could not set nil as the value for the key age.)
            if (value) {
                // 给模型中属性赋值
                [objc setValue:value forKey:key];
            }
        }
        return objc;
    }
     
    @end

    2 模型中嵌套模型(模型属性是另外一个模型对象)

    #import "NSObject+Mod.h"
    #import <objc/message.h>
    @implementation NSObject (Mod) // 获取类里面所有方法 // class_copyMethodList(__unsafe_unretained Class cls, unsigned int *outCount)// 本质:创建谁的对象 // 获取类里面属性 // class_copyPropertyList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>) // Ivar:成员变量 以下划线开头 // Property:属性 + (instancetype)modelWithDict2:(NSDictionary *)dict { // 1.创建对应的对象 id objc = [[self alloc] init]; // 2.利用runtime给对象中的属性赋值 /** class_copyIvarList: 获取类中的所有成员变量 Ivar:成员变量 第一个参数:表示获取哪个类中的成员变量 第二个参数:表示这个类有多少成成员变量,传入一个Int变量地址,会自动给这个变量赋值 返回值Ivar *:指的是一个ivar数组,会把所有成员属性放在一个数组中,通过返回的数组就能全部获取到。 count: 成员变量个数 */ unsigned int count = 0; // 获取类中的所有成员变量 Ivar *ivarList = class_copyIvarList(self, &count); // 遍历所有成员变量 for (int i = 0; i < count; i++) { // 根据角标,从数组取出对应的成员变量 Ivar ivar = ivarList[i]; // 获取成员变量名字 NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)]; // 获取成员变量类型 NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)]; // 替换: @"NSString" -> NSString ivarType = [ivarType stringByReplacingOccurrencesOfString:@""" withString:@""]; ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""]; // 处理成员变量名->字典中的key(去掉 _ ,从第一个角标开始截取) NSString *key = [ivarName substringFromIndex:1]; // 根据成员属性名去字典中查找对应的value id value = dict[key]; // 二级转换:如果字典中还有字典,也需要把对应的字典转换成模型 // 判断下value是否是字典,并且是自定义对象才需要转换 if ([value isKindOfClass:[NSDictionary class]] && ![ivarType hasPrefix:@"NS"]) { // 字典转换成模型 userDict => User模型, 转换成哪个模型 // 根据字符串类名生成类对象 Class modelClass = NSClassFromString(ivarType); if (modelClass) { // 有对应的模型才需要转 // 把字典转模型 value = [modelClass modelWithDict2:value]; } } // 给模型中属性赋值 if (value) { [objc setValue:value forKey:key]; } } return objc; } @end

    3 数组中装着模型(模型属性是数组,数组中是字典模型对象)

    #import "NSObject+Item.h"
    #import <objc/message.h>
    
    @implementation NSObject (Item)
    
    // Runtime:根据模型中属性,去字典中取出对应的value给模型属性赋值
    // 思路:遍历模型中所有属性->使用运行时
    + (instancetype)modelWithDict3:(NSDictionary *)dict
    {
        // 1.创建对应的对象
        id objc = [[self alloc] init];
        
        // 2.利用runtime给对象中的属性赋值
        /**
         class_copyIvarList: 获取类中的所有成员变量
         Ivar:成员变量
         第一个参数:表示获取哪个类中的成员变量
         第二个参数:表示这个类有多少成员变量,传入一个Int变量地址,会自动给这个变量赋值
         返回值Ivar *:指的是一个ivar数组,会把所有成员属性放在一个数组中,通过返回的数组就能全部获取到。
         count: 成员变量个数
         */
        unsigned int count = 0;
        // 获取类中的所有成员变量
        Ivar *ivarList = class_copyIvarList(self, &count);
        
        // 遍历所有成员变量
        for (int i = 0; i < count; i++) {
            // 根据角标,从数组取出对应的成员变量
            Ivar ivar = ivarList[i];
            
            // 获取成员变量名字
            NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
            
            // 处理成员属性名->字典中的key(去掉 _ ,从第一个角标开始截取)
            NSString *key = [ivarName substringFromIndex:1];
            
            // 根据成员属性名去字典中查找对应的value
            id value = dict[key];
            
            
            //--------------------------- <#我是分割线#> ------------------------------//
            //
            
            // 三级转换:NSArray中也是字典,把数组中的字典转换成模型.
            // 判断值是否是数组
            if ([value isKindOfClass:[NSArray class]]) {
                // 判断对应类有没有实现字典数组转模型数组的协议
                // arrayContainModelClass 提供一个协议,只要遵守这个协议的类,都能把数组中的字典转模型
                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 modelWithDict3:dict];
                        [arrM addObject:model];
                    }
                    
                    // 把模型数组赋值给value
                    value = arrM;                
                }
            }
            
            // 如果模型属性数量大于字典键值对数理,模型属性会被赋值为nil,而报错
            if (value) {
                // 给模型中属性赋值
                [objc setValue:value forKey:key];
            }
        }
        return objc;
    }
    
    @end
  • 相关阅读:
    模板 快速询问GCD
    Educational Codeforces Round 13 A. Johny Likes Numbers 水题
    Codeforces Round #102 (Div. 1) A. Help Farmer 暴力分解
    CDOJ 1402 三角形棋盘上的博弈游戏 状压DP
    CDOJ 1401 谭爷的黑暗沙拉 数学
    Bootstrap3.0学习第七轮(按钮)
    Bootstrap3.0学习第六轮(表单)
    Bootstrap3.0学习第五轮(表格)
    Bootstrap3.0学习第四轮(排版)
    Bootstrap3.0学习第三轮(栅格系统案例)
  • 原文地址:https://www.cnblogs.com/muzijie/p/7306666.html
Copyright © 2020-2023  润新知