runtime字典转模型

runtime字典转模型

  • 遍历模型中所有的成员变量ivar
  • 再到字典中去找,用KVC给模型赋值
  • 字典中的Dictionary,二级转换成模型
  • 字典中有Array,根据方法返回的类型,转换成模型
@interface NSObject (Model)
/**
 *  实现二级字典转模型
 */
+ (instancetype)modelWithDict:(NSDictionary *)dict;
/**
 *  数组中的模型
 */
+ (NSDictionary *)objectClassInArray;
@end

#import <objc/message.h>
@implementation NSObject (Model)

+ (instancetype)modelWithDict:(NSDictionary *)dict
{
    // 创建对应的类对象
    id objc = [[self alloc] init];
    
    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList([self class], &count);
    
    for (NSInteger i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        
        // 获取成员名
        NSString *propertyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        // 成员属性类型
        NSString *propertyType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        // _source --- @"NSString"
//        NSLog(@"1---%@ --- %@", propertyName, propertyType);
        // 获取key到字典里找: _source->source
        NSString *key = [propertyName substringFromIndex:1];
        
        id value = dict[key];
        
        // 1.二级转换,字典里的字典模型
        // 值是字典,成员变量的类型不是字典,才需要转化
        if ([value isKindOfClass:[NSDictionary class]] && ![propertyType containsString:@"NS"]) {
            
            // \" 看做一个字符,转义字符
            // 字符串截取   @"@\"User\""== @\"User\" ->  User\"            // 去掉两边的引用号 \"
            NSRange range = [propertyType rangeOfString:@"\""];
            // 截取双引号 后面的东西
            propertyType = [propertyType substringFromIndex:range.location + range.length];
            // User\" -> User
            range = [propertyType rangeOfString:@"\""];
            propertyType = [propertyType substringToIndex:range.location];
            
            // 获取到转换的类
            Class modelClass = NSClassFromString(propertyType);
            if (modelClass) {
                // 递归
                value = [modelClass modelWithDict:value];
            }
        }

        // 2.字典里的数组
        if ([value isKindOfClass:[NSArray class]]) { // [propertyType isEqualToString:@"@\"NSArray\""]
            if ([self respondsToSelector:@selector(objectClassInArray)]) {
                NSString *type = [self objectClassInArray][key];
                
                Class modelClass = NSClassFromString(type);
                NSMutableArray *modelArray = [NSMutableArray array];
                
                for (NSDictionary *dict in value) {
                    id model = [modelClass modelWithDict:dict];
                    [modelArray addObject:model];
                }
                value = modelArray;
            }
        }
//        NSLog(@"2---%@ --- %@", propertyName, propertyType);
        
        if (value) {
            // KVC赋值:不能传空的,字典中没有值,就不管了
            [objc setValue:value forKey:key];
        }
    }
    // 释放
    free(ivarList);
    return objc;
}
@end

举个例子

  • MGStudent模型
@interface MGStudent : NSObject
/** 名字 */
@property (nonatomic, copy) NSString *name;
/** 年龄 */
@property (nonatomic, assign) NSInteger age;
/** 有一本书 */
@property (nonatomic, strong) MGBook *book;
/** 拥有的书本 */
@property (nonatomic, strong) NSArray *books;
@end

@implementation MGStudent
+ (NSDictionary *)objectClassInArray
{
    return @{ @"books" : @"MGBook" };
}
@end
  • MGBook模型
@interface MGBook : NSObject
/** 书名 */
@property (nonatomic, copy) NSString *bookName;
/** 出版社 */
@property (nonatomic, copy) NSString *publisher;
/** 价格 */
@property (nonatomic, assign) double price;
@end

执行结果:

字典数据
字典转模型
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 设计模型:字典转模型的第一步模型属性,通常需要跟字典中的key一一对应问题:一个一个的生成模型属性,很慢?需求:能...
    翻这个墙阅读 250评论 0 0
  • 字典转模型一般都两种方式,1、图方便用的mj框架;2、自己在模型中写类方法,用KVC实现。 换换口味,尝试下run...
    动感超人丶阅读 160评论 0 0
  • 本文分为两部分: 一:教你怎样一部获取成员属性(通过NSObject+autoLogProperty分类)二:对比...
    CoderDancer阅读 966评论 1 17
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,733评论 7 64
  • 静听竹风暖 熟视云雾娈。 山间花正欢, 仙境梦又幻?
    与你画夕阳阅读 312评论 9 0