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
仅供参考!