利用 runtime 原理,获取模型中所有实例变量列表,根据实例变量以此获取模型中成员变量的名称和属性类型,区分Foundation和自定义属性,需要对NSDictionary和NSArray类型做单独处理。
下面代码是一个简单的原理实现Demo,真正的框架中需要考虑很多问题,例如可以设置只有某个数组中的属性名才允许进行字典和模型的转换,将属性名换为其他key去字典中取值,白名单,黑名单等等设置
+ (instancetype)modelWithDict:(NSDictionary *)dict
{
id objc = [[self alloc] init];
unsigned int count = 0;
Ivar *ivarList = class_copyIvarList(self, &count);
for (int i = 0; i < count; i++) {
// 实例变量
Ivar ivar = ivarList[i];
// 获取成员属性名
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSString *key = [ivarName substringFromIndex:1];
id value = dict[key];
if (value == nil) {
continue;
}
// 获得成员变量的类型
NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
NSLog(@"ivar - %@, type - %@", ivarName, ivarType);
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
if ([value isKindOfClass:[NSDictionary class]]) {
Class modelClass = NSClassFromString(ivarType);
value = [modelClass modelWithDict:value];
} else if ([value isKindOfClass:[NSArray class]]) {
if ([self respondsToSelector:@selector(arrayContainModelClass)]) {
NSString *type = [self arrayContainModelClass][key];
Class classModel = NSClassFromString(type);
NSMutableArray *arrM = [NSMutableArray array];
for (NSDictionary *dict in value) {
id model = [classModel modelWithDict:dict];
if (model) {
[arrM addObject:model];
}
}
value = arrM;
}
}
if (value) {
[objc setValue:value forKey:key];
}
}
return objc;
}