字典转模型




      俺们知道,在iOS开发中,字典是经常出现的一个东东,那么我们直接操作字典呢,很容易产生把眼睛找瞎也找不到的BUG。为什么这么说呢?比如:本身有这么个 tmpDict["name"] 东西,而你却写成了  tmpDict["nane"]  ; 这在Xcode中是不会报错的,而你的程序可能就会莫名其妙的崩掉,此时最好的解决方案就是将字典转换成模型。

     在使用模型开发时,你一个点语法,点出来的属性,点错了编译器会立刻报错,干掉BUG于摇篮之中~~~~

  

    这里我写了一个分类,主要用于将字典转换成模型:

     当然,实现还不够完美~~~哈哈

     当字典是这样的时候:

  

@{
                           @"name" : @"jack",
                           @"age" : @20,
                           @"height" : @"1.55",
                           @"dog" : @{
                                   @"name" : @"wangcai",
                                   @"price" : @"100",
                                   @"bone" : @{
                                           @"name" : @"狗骨头",
                                           @"weight" : @"200"
                                           }
                                   },
                           @"books" : @[
                                   @{
                                       @"name" : @"好书",
                                       @"price" : @10000000.6,
                                       @"publisher" : @"清华大学出版社",
                                       @"author" : @"张宇清"
                                       },
                                   @{
                                       @"name" : @"坏书",
                                       @"price" : @14.6,
                                       @"publisher" : @"北京大学出版社"
                                       }
                                   ],
                           @"money" : @"100"
                           };

我们可以看到 在字典中,有 普通 字符串 、double类型、int类型、dog自定义类型、NSArray类型;

现在我要做的事就是将这些数据全部转换成模型;


        NSObject+Extension.h

<span style="font-size:18px;">#import <Foundation/Foundation.h>

@interface NSObject (Extension)
/**
 *  假设模型中又数组类型的成员属性,那么传入该数组类型的成员属性名称,
 即可得到数组中包含的自定义对象类型

 */
- (Class)classForProperty:(NSString *)name;
/**
 *  提供方法,将字典传入进去
 */
- (void)setDict:(NSDictionary *)dict;


/**
 *  拿对象来调用该方法,就可将字典转换为模型
 */
+ (instancetype)objectWithDict:(NSDictionary *)dict;
@end
</span>

     NSObject+Extension.m

<span style="font-size:18px;">#import "NSObject+Extension.h"
#import <objc/runtime.h>
#import "Book.h"
#import "Dog.h"

@implementation NSObject (Extension)



- (void)setDict:(NSDictionary *)dict
{
    Class c = self.class;
    while (c && c != [NSObject class]) {
        // 用来存储成员变量的数量
        unsigned int outCount = 0;
        
        // 获得Dog类的所有成员变量
        Ivar *ivars = class_copyIvarList(c, &outCount);
        
        // 遍历所有的成员变量
        for (int i = 0; i<outCount; i++) {
            // 取出i位置对应的成员变量
            Ivar ivar = ivars[i];
            
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            // 成员变量 --> 属性名
            
            key = [key substringFromIndex:1]; // name, age, books, dog , books
            
            // 取出字典值
            id value = dict[key];  // 如果是最基本的类型就直接获得,如果是特殊类型,后面会重新赋值
            // 字典中没有这个key对应的值
            if (value == nil) continue;
            
            // 获得成员变量的类型
            // @"NSArray", d,i, @"NSString"
            NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
            
//            if ([type isEqualToString:@"@\"Dog\""]) {
//                value = [Dog objectWithDict:value];
//            }
            
            NSRange range = [type rangeOfString:@"@"];
            if (range.location != NSNotFound) { // 能找到@  type == @"Dog"
                // 如果都是 @ 开头的数据类型
                type = [type substringWithRange:NSMakeRange(2, type.length - 3)];
                
                if (![type hasPrefix:@"NS"]) { // 如果不是NS开头,说明是普通对象类型
                    // NSString -- Class  通俗的说,这不是继承,而是类包含类
                    Class class = NSClassFromString(type);
                    value = [class objectWithDict:value];
                }
                
                /**
                 *  判断NSArray类型
                 */
               if ([type isEqualToString:@"NSArray"]) { // 如果为NSArray类型
                   NSArray * tmpArr = (NSArray*)value; // 将value强转为NSArray,
                   NSMutableArray * bookArr = [NSMutableArray array]; // 用于保存对象(对象来自于数组中的字典,再一次封装到新数组中)
                    for (int i=0; i< tmpArr.count; i++) { // 遍历数组中字典
                        NSDictionary * dict = tmpArr[i];
                        Class clazz = [self classForProperty:key]; // 通过成员变量名获得对应的类字节码类型
                       if (clazz) { // 判空操作,如果是nil程序会崩溃
                            id obj  = [clazz objectWithDict:dict]; // 获得
                            [bookArr addObject:obj];
                        }
                    }
                   value = bookArr;
                }
            }
            
            // 将字典中的值设置到模型上
            [self setValue:value forKeyPath:key];
        }
        
        free(ivars);
        
        c = [c superclass];  // 如果有父类就接着调用
    }
}

+ (instancetype)objectWithDict:(NSDictionary *)dict
{
    NSObject *obj = [[self alloc] init];
    [obj setDict:dict];
    return obj;
}
@end</span>



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值