菜鸟进化史之RunTime实战字典转模型

Bison

1

很久没更新文章了,由于最近公司项目比较赶,所以……. 下面可以看到一个菜鸟的进化史哦。赶紧围观吧。😄 字典转模型在我还是菜鸟的时候,说实话,老老实实在模型里面写的如下代码

1.手动解析

//手动解析
 - (instancetype)initWithDic
{
    self = [super init];
    if (self) {
        xxx = dic[@"xxx"];
        ...
    }
    return self;
}

2.KVC解析

//kvc解析
 - (instancetype)initWithDic
{
    self = [super init];
    if (self) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

3.第三方框架


是不是很熟悉?我想每个人从开始接触iOS开发到现在都会有一个进化的过程。就这样写了很久直到我走出那家公司,去其他公司面试,被虐的体无完肤。各种炫酷装逼底层层出不穷,面试是一种成长的机会,我是这么认为的。只有当自己看到了差距看到了自己的不足时,为了生存,才会逼自己一把。让自己变的更加的优秀。上面是自己的一点感悟,希望对读者有所帮助。下面我们进入正题。

一般的解析我个人是用KVC,有时候也会用一些第三方的框架,MJ的MJExtensionJsonModel等。听说最近面试对于RunTime问的比较的火,说实话,我对于底层的东西学的很烂,因为实际应用当中很少用到,学着学着过断时间也会忘记。网上的资料也很多,我也来凑下热闹😄下面是我学习RunTime时的一点实战性的东西。

1.首先创建一个继承NSObject的分类,名字叫DicToModel

2.增加一个方法用于字典转模型,方法名如下:


+ (instancetype)createModelWithDict:(NSDictionary *)dict;

3.导入runtime所需的头文件#import <objc/message.h>

4.接下来我们将实现我们在.h文件里面的方法

+ (instancetype)createModelWithDict:(NSDictionary *)dict{
    
    // 1.创建对应类的对象
    id model = [[self alloc] init];
    
    // runtime:遍历模型中所有成员属性,去字典中查找
    // 属性定义在哪,定义在类,类里面有个属性列表(数组)
    
    // 遍历模型所有成员属性
    // ivar:成员属性
    // class_copyIvarList:把成员属性列表复制一份给你
    // Ivar *:指向Ivar指针
    // Ivar *:指向一个成员变量数组
    // class:获取哪个类的成员属性列表
    // count:成员属性总数
    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList([self class], &count);
    for (int i = 0 ; i < count; i++) {
        // 获取成员属性
        Ivar ivar = ivarList[i];
        
        // 获取成员名
        NSString *propertyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        // 获取key
        NSString *key = [propertyName substringFromIndex:1];
        
        // user value:字典
        // 获取字典的value
        id value = dict[key];
        // 给模型的属性赋值
        // value:字典的值
        // key:属性名
        
        // 成员属性类型
        NSString *propertyType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        // 二级转换
        // 值是字典,成员属性的类型不是字典,才需要转换成模型
        if ([value isKindOfClass:[NSDictionary class]] && ![propertyType containsString:@"NSDictionary"]) { // 需要字典转换成模型
            // @"@\"xxxx\"" 截取类名字符串
            NSRange range = [propertyType rangeOfString:@"\""];
            propertyType = [propertyType substringFromIndex:range.location + range.length];
            // xxxx\"";
            range = [propertyType rangeOfString:@"\""];
            propertyType = [propertyType substringToIndex:range.location];
            // 获取需要转换类的类对象
            Class modelClass =  NSClassFromString(propertyType);
            
            if (modelClass) {
                value =  [modelClass createModelWithDict:value];
            }
        }
        if (value) {// KVC赋值:不能传空
            [model setValue:value forKey:key];
            
        }
        
    }
    
    
    return model;
}

以上代码实现了2层字典转模型,一般情况都没什么问题。如需增加其他的情况只需增加value isKindOfClass判断做一些处理即可,具体详细的请看代码注释哦!下面我们来看看怎么调用吧!代码如下

- (void)viewDidLoad {
    [super viewDidLoad];
    // 解析Plist
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
    NSArray *dictArr = dict[@"statuses"];
    NSMutableArray *statusesData = [NSMutableArray array];
    // 遍历字典数组
    for (NSDictionary *dict in dictArr) {
        //传字典给我们写的分类返回一个status的模型
        Status *status = [Status createModelWithDict:dict];
        [statusesData addObject:status];
    }
    NSLog(@"%@",statusesData);
}

学习iOS开发的app上线啦,点此来围观吧

更多经验请点击

好文推荐:分分钟解决iOS开发中App启动动画广告的功能


分享文章