cordova/phonegap

iOS简单实现字典转Model

2018-10-09  本文已影响65人  Miaoz0070

翻看了很多解析库,发现库有的强依赖、有的size有点超过预期,所以就不想引入第三方,由于公司的项目需要输出,对于引入第三方要求比较高,项目中对于请求解析也不是很繁琐,所以说这里根据网上的搜索及自己的整合,提供一个NSObject的类别,供大家查看使用,可以直接使用,原理也是利用runtime实现的。

NSObject+QHModelDicTransform.h
//
//  NSObject+QHModelDicTransform.h
//  YYStudio_LoanSDK
//
//  Created by Miaoz on 2018/8/23.
//  Copyright © 2018年 Miaoz. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol QHModelDicTransform <NSObject>

@optional

/**
 *  数组中存储的类型
 *
 *  @return key --- 属性名,  value --- 数组中存储的类型
 */
+ (NSDictionary *)qh_objectClassInArray;

/**
 *  替换一些字段
 *
 *  @return key -- 模型中的字段, value --- 字典中的字段
 */
+ (NSDictionary *)qh_propertykeyReplacedWithValue;

@end

@interface NSObject (QHModelDicTransform)<QHModelDicTransform>
//字典转模型
+ (instancetype)qh_initWithDictionary:(NSDictionary *)dic;
@end

NSObject+QHModelDicTransform.m
//
//  NSObject+QHModelDicTransform.m
//  YYStudio_LoanSDK
//
//  Created by Miaoz on 2018/8/23.
//  Copyright © 2018年 Miaoz. All rights reserved.
//

#import "NSObject+QHModelDicTransform.h"
#import <objc/runtime.h>
NSString *const YJClassType_object  =   @"对象类型";
NSString *const YJClassType_basic   =   @"基础数据类型";
NSString *const YJClassType_other   =   @"其它";

@implementation NSObject (QHModelDicTransform)

//获取属性的类型
- (NSDictionary *)propertyTypeFromProperty:(objc_property_t)property
{
    //获取属性的类型, 类似 T@"NSString",C,N,V_name    T@"UserModel",&,N,V_user
    NSString *propertyAttrs = @(property_getAttributes(property));
    
    NSMutableDictionary *dicPropertyType = [NSMutableDictionary dictionary];
    
    //截取类型
    NSRange commaRange = [propertyAttrs rangeOfString:@","];
    NSString *propertyType = [propertyAttrs substringWithRange:NSMakeRange(1, commaRange.location - 1)];
    NSLog(@"属性类型:%@, %@", propertyAttrs, propertyType);
    
    if ([propertyType hasPrefix:@"@"] && propertyType.length > 2) {
        //对象类型
        NSString *propertyClassType = [propertyType substringWithRange:NSMakeRange(2, propertyType.length - 3)];
        [dicPropertyType setObject:propertyClassType forKey:@"classType"];
        [dicPropertyType setObject:YJClassType_object forKey:@"type"];
    }
    else if ([propertyType isEqualToString:@"q"]) {
        //NSInteger类型
        [dicPropertyType setObject:@"NSInteger" forKey:@"classType"];
        [dicPropertyType setObject:YJClassType_basic forKey:@"type"];
    }
    else if ([propertyType isEqualToString:@"d"]) {
        //CGFloat类型
        [dicPropertyType setObject:@"CGFloat" forKey:@"classType"];
        [dicPropertyType setObject:YJClassType_basic forKey:@"type"];
    }
    else if ([propertyType isEqualToString:@"c"]) {
        //BOOL类型
        [dicPropertyType setObject:@"BOOL" forKey:@"classType"];
        [dicPropertyType setObject:YJClassType_basic forKey:@"type"];
    }
    else {
        [dicPropertyType setObject:YJClassType_other forKey:@"type"];
    }
    return dicPropertyType;
}



+ (instancetype)qh_initWithDictionary:(NSDictionary *)dic
{
    id myObj = [[self alloc] init];
    
    unsigned int outCount;
    
    //获取类中的所有成员属性
    objc_property_t *arrPropertys = class_copyPropertyList([self class], &outCount);
    
    for (NSInteger i = 0; i < outCount; i ++) {
        objc_property_t property = arrPropertys[i];
        
        //获取属性名字符串
        //model中的属性名
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
        //字典中的属性名
        NSString *newPropertyName;
        
        if ([self respondsToSelector:@selector(qh_propertykeyReplacedWithValue)]) {
            newPropertyName = [[self qh_propertykeyReplacedWithValue] objectForKey:propertyName];
        }
        if (!newPropertyName) {
            newPropertyName = propertyName;
        }
        
        NSLog(@"属性名:%@", propertyName);
        
        id propertyValue = dic[newPropertyName];
        if (propertyValue == nil) {
            continue;
        }
        
        //获取属性是什么类型的
        NSDictionary *dicPropertyType = [self propertyTypeFromProperty:property];
        NSString *propertyClassType = [dicPropertyType objectForKey:@"classType"];
        NSString *propertyType = [dicPropertyType objectForKey:@"type"];
        if ([propertyType isEqualToString:YJClassType_object]) {
            if ([propertyClassType isEqualToString:@"NSArray"] || [propertyClassType isEqualToString:@"NSMutableArray"]) {
                //数组类型
                if ([self respondsToSelector:@selector(qh_objectClassInArray)]) {
                    id propertyValueType = [[self qh_objectClassInArray] objectForKey:propertyName];
                    if ([propertyValueType isKindOfClass:[NSString class]]) {
                        propertyValue = [NSClassFromString(propertyValueType) qh_initWithArray:propertyValue];
                    }
                    else {
                        propertyValue = [propertyValueType qh_initWithArray:propertyValue];
                    }
                    
                    if (propertyValue != nil) {
                        [myObj setValue:propertyValue forKey:propertyName];
                    }
                }
                
            }
            else if ([propertyClassType isEqualToString:@"NSDictionary"] || [propertyClassType isEqualToString:@"NSMutableDictionary"]) {
                //字典类型   不考虑,一般不会用字典,用自定义model
                
            }
            else if ([propertyClassType isEqualToString:@"NSString"]) {
                //字符串类型
                if (propertyValue != nil) {
                    [myObj setValue:propertyValue forKey:propertyName];
                }
            }
            else {
                //自定义类型
                propertyValue = [NSClassFromString(propertyClassType) qh_initWithDictionary:propertyValue];
                if (propertyValue != nil) {
                    [myObj setValue:propertyValue forKey:propertyName];
                }
            }
        }
        else if ([propertyType isEqualToString:YJClassType_basic]) {
            //基本数据类型
            if ([propertyClassType isEqualToString:@"c"]) {
                //bool类型
                NSString *lowerValue = [propertyValue lowercaseString];
                if ([lowerValue isEqualToString:@"yes"] || [lowerValue isEqualToString:@"true"]) {
                    propertyValue = @(YES);
                } else if ([lowerValue isEqualToString:@"no"] || [lowerValue isEqualToString:@"false"]) {
                    propertyValue = @(NO);
                }
            }
            else {
                propertyValue = [[[NSNumberFormatter alloc] init] numberFromString:propertyValue];
            }
            
            if (propertyValue != nil) {
                [myObj setValue:propertyValue forKey:propertyName];
            }
        }
        else {
            //其他类型
        }
    }
    
    free(arrPropertys);
    
    return myObj;
}

//数组转模型数组,现在还用不了,因为还没有方法知道数组中保存的是什么类型,后面会处理
+ (instancetype)qh_initWithArray:(NSArray *)arr
{
  
    NSMutableArray *arrModels = [NSMutableArray array];
    
    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj isKindOfClass:[NSArray class]]) {
            [arrModels addObject:[self qh_initWithArray:obj]];
        }
        else {
            id model = [self qh_initWithDictionary:obj];
            [arrModels addObject:model];
        }
    }];
    return arrModels;
}


@end

仅供参考!

上一篇下一篇

猜你喜欢

热点阅读