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
执行结果:
字典数据
字典转模型