自定义字典转模型类

2016-11-04  本文已影响0人  y夜无眠

现在大家提起字典转模型,都会想到使用MJExtension第三方库.这那里面封装了很多的功能,确实非常方便好用, 但我现在的需求仅仅只是从json解析过来的数据传值给我定义的modal,不需要用那么多功能,自然也就不想拖那么多多余的类进我的工程里面. 所以我就自定义了一个字典转模型的分类实现我这一简单的功能:

解决的问题:当json里的字段和Modal里的属性名一致时,可以直接用: - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues; 当不一致,如后台又加了字段,删或改了字段, 再用那个方法你运行就直接崩溃了.我定义的这个分类就是解决这个崩溃的问题!

#pragma mark --取得类中的所以属性名
- (NSMutableArray *)getProperties:(Class)class
{
    unsigned int count;
    
    objc_property_t *properties = class_copyPropertyList(class, &count);
    
    NSMutableArray * propertyArray = [NSMutableArray array];
    for (int i = 0; i<count; i++) {
        // objc_property_t 属性类型
        objc_property_t property = properties[i];
        // 获取属性的名称 C语言字符串
        const char *cName = property_getName(property);
        // 转换为Objective C 字符串
        NSString *nameStr = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
        [propertyArray addObject:nameStr];
    }
    return propertyArray;
}
#pragma mark -- 通过字符串来创建该字符串的Setter方法,并返回
- (SEL) creatSetterWithPropertyName: (NSString *) propertyName{
//    只把首字母变成大写,其它的不变
    NSString * firstStr = [propertyName substringToIndex:1];
    NSString * secondStr = [propertyName substringFromIndex:1];
    //1.首字母大写
    firstStr = firstStr.capitalizedString;
    
    //2.拼接上set关键字
    propertyName = [NSString stringWithFormat:@"set%@%@:", firstStr,secondStr];
    //3.返回set方法
    return NSSelectorFromString(propertyName);
}
#pragma mark --利用传入的字典给类属性赋值
- (instancetype) assginToPropertyWithDictionary: (NSDictionary *) data
{
    if (data == nil) {
        return nil;
    }
    
//    获取所有的属性值
    NSMutableArray * array = [self getProperties:[self class] ];
    
    NSMutableDictionary * valueDictionary = [NSMutableDictionary dictionary];
    NSMutableArray * propertyArray = [NSMutableArray array];
    
    for (NSString * string in array) {
        if ([[data allKeys] containsObject:string]) {
            [valueDictionary setObject:data[string] forKey:string];
        }else{
            [propertyArray addObject:string];
        }
    }
    
    ///2.循环遍历字典key, 并且动态生成实体类的setter方法,把字典的Value通过setter方法
    ///赋值给实体类的属性
    for (int i = 0; i < valueDictionary.count; i ++) {  //当字典中键值比较多时.
        
        NSString * propertyStr = [valueDictionary allKeys][i];
        ///2.1 通过getSetterSelWithAttibuteName 方法来获取实体类的set方法
        SEL setSel = [self creatSetterWithPropertyName:propertyStr];
        
        if ([self respondsToSelector:setSel]) {
            ///2.2 获取字典中key对应的value
            NSString  *value = [NSString stringWithFormat:@"%@", valueDictionary[propertyStr]];
            ///2.3 把值通过setter方法赋值给实体类的属性
            [self performSelectorOnMainThread:setSel
                                   withObject:value
                                waitUntilDone:[NSThread isMainThread]];
        }
    }
    
    for (int i = 0; i<propertyArray.count; i++) {  //当类属性比较多时
        SEL setSel = [self creatSetterWithPropertyName:propertyArray[i]];
        if ([self respondsToSelector:setSel]) {
            ///2.2 获取字典中key对应的value
            NSString * str = @"";
            NSString  *value = [NSString stringWithFormat:@"%@", str];
            
            ///2.3 把值通过setter方法赋值给实体类的属性
            [self performSelectorOnMainThread:setSel
                                   withObject:value
                                waitUntilDone:[NSThread isMainThread]];
        }
    }
    return self;
}

建个NSObject的分类,定一个类方法.

+ (instancetype)valueWithDictionary:(NSDictionary *)dict
{
    return [[self alloc] assginToPropertyWithDictionary:dict];
}

搞定,针对模型类属性与json字段不一致的情况,直接将这个分类拖进去,调用类方法,既能传值,又不会导致崩溃的情况!

上一篇下一篇

猜你喜欢

热点阅读