请先看上篇博客: KVC实现字典转模型
思路: 利用运行时,取出模型中所有的属性,根据模型的属性名,去字典中查找对应的key,然后给模型中的属性赋值.
实现: 提供一个NSObject分类,专门用来字典转模型,以后所有的模型都可以通过这个分类来转.
知识点:
① 给NSObject写一个分类,专门用来 字典转模型
② 成员变量和属性的区别
1. 例如 @property NSString *name; 此时name就是属性
2. 属性name生成_name 就是 成员变量
③ 利用runtime获得模型中成员变量的数组,遍历成员变量数组,取出模型中所有的成员变量,并转为字符串,并且去掉下划线.就是属性名.
/*
param1:Class 获取哪个类的成员变量
param2:count 成员变量个数
*/
unsigned int count = 0;
// Ivar 是一个成员变量数组
Ivar *ivarList = class_copyIvarList(self, &count);
// 遍历
for (int i = 0; i < count; ++i) {
// 获取成员变量
Ivar ivar = ivarList[i];
// 获取成员变量名字
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//NSLog(@"%@",ivarName);
// 获取成员变量的类型
NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// NSLog(@"%@",ivarType); //@"ZYUserItem"
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
// NSLog(@"%@",ivarType); // ZYUserItem
// 获取key
NSString *key = [ivarName substringFromIndex:1];
④ 根据属性名去字典中查找value
⑤给模型中的属性赋值(KVC) setValue:forKey:
ViewController文件
// Created by 朝阳 on 2018/1/23.
// Copyright © 2018年 sunny. All rights reserved.
//
#import "ViewController.h"
#import "NSDictionary+Property.h"
#import "ZYStatusItem.h"
#import "NSObject+Model.h"
#import "ZYUserItem.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1. 加载plist文件
// 获取文件全路径
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
// 文件全路径
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
// 设置模型,创建属性代码 ==> dict
//[dict[@"user"] createPropertyCode]; // 自动生成属性
// 字典转模型
ZYStatusItem *item = [ZYStatusItem modelWithDict:dict];
ZYUserItem *userItem = item.user;
NSLog(@"%@",userItem.name);
}
@end
NSObject+Model文件
#import "NSObject+Model.h"
#import
@implementation NSObject (Model)
/*
获取类里面所有方法
class_copyMethodList(Class _Nullable __unsafe_unretained cls, unsigned int * _Nullable outCount)
// Property 属性
class_copyPropertyList(Class _Nullable __unsafe_unretained cls, unsigned int * _Nullable outCount)
// Ivar 成员变量 _开头
class_copyIvarList(Class _Nullable __unsafe_unretained cls, unsigned int * _Nullable outCount)
*/
// 本质:创建谁的对象
// 字典转模型
+ (instancetype)modelWithDict:(NSDictionary *)dict
{
id objc = [[self alloc] init];
// runtime:根据模型中的属性,去字典中取出对应的key, 然后给模型属性赋值
//1.获取模型中所有属性 key
/*
param1:Class 获取哪个类的成员变量
param2:count 成员变量个数
*/
unsigned int count = 0;
// Ivar 是一个成员变量数组
Ivar *ivarList = class_copyIvarList(self, &count);
// 遍历
for (int i = 0; i < count; ++i) {
// 获取成员变量
Ivar ivar = ivarList[i];
// 获取成员变量名字
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//NSLog(@"%@",ivarName);
// 获取成员变量的类型
NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// NSLog(@"%@",ivarType); //@"ZYUserItem"
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
// NSLog(@"%@",ivarType); // ZYUserItem
// 获取key
NSString *key = [ivarName substringFromIndex:1];
//2.根据属性名去字典中查找value
id value = dict[key];
// 二级转换:判断下value是否是字典,如果是,字典转为对应的模型
// 并且是自定义对象的字典才需要转换: 成员变量的类型前缀不是NS.
if ([value isKindOfClass:[NSDictionary class]] && ![ivarType hasPrefix:@"NS"]) {
// 字典转模型 => userDict => User模型
//1. 获取哪个类型?
// 获取成员变量的类型
// NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// // NSLog(@"%@",ivarType); //@"ZYUserItem"
// ivarType = [ivarType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
// ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
// // NSLog(@"%@",ivarType); // ZYUserItem
//
//2. 获取哪个类
Class modelClass = NSClassFromString(ivarType);
value = [modelClass modelWithDict:value];
}
//3.给模型中属性赋值 KVC
if (value) {
[objc setValue:value forKey:key];
}
}
return objc;
}
//void test (int *count)
//{
// *count = 3;
//}
@end
ZYUserItem文件
#import
@interface ZYUserItem : NSObject
@property (nonatomic, strong) NSString *profile_image_url;
@property (nonatomic, assign) BOOL vip;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger mbrank;
@property (nonatomic, assign) NSInteger mbtype;
@end