作品链接:http://www.jianshu.com/users/1e0f5e6f73f6/top_articles
1 自动打印属性字符串分类
- 提供一个分类,专门根据字典生成对应的属性字符串。
@implementation NSObject (Property)
+ (void)PH_createPropertyCodeWithDict:(NSDictionary *)dict
{
NSMutableString *strM = [NSMutableString string];
// 遍历字典
[dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull propertyName, id _Nonnull value, BOOL * _Nonnull stop) {
NSLog(@"%@,%@",propertyName,[value class]);
NSString *code;
if ([value isKindOfClass:NSClassFromString(@"__NSCFString")]) {
code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSString *%@;",propertyName]
;
} else if ([value isKindOfClass:NSClassFromString(@"__NSCFNumber")]){
code = [NSString stringWithFormat:@"@property (nonatomic, assign) int %@;",propertyName]
;
}else if ([value isKindOfClass:NSClassFromString(@"__NSCFArray")]){
code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSArray *%@;",propertyName]
;
}else if ([value isKindOfClass:NSClassFromString(@"__NSCFDictionary")]){
code = [NSString stringWithFormat:@"@property (nonatomic, strong) NSDictionary *%@;",propertyName]
;
} else if ([value isKindOfClass:NSClassFromString(@"__NSCFBoolean")]){
code = [NSString stringWithFormat:@"@property (nonatomic, assign) BOOL %@;",propertyName]
;
}
[strM appendFormat:@"\n%@\n",code];
}];
NSLog(@"%@",strM);
}
@end
2 字典转模型的方式一:KVC
@implementation Status
+ (instancetype)statusWithDict:(NSDictionary *)dict
{
Status *status = [[self alloc] init];
[status setValuesForKeysWithDictionary:dict];
return status;
}
@end
- KVC字典转模型弊端:必须保证,模型中的属性和字典中的key一一对应。
- 如果不一致,就会调用
[<Status 0x7fa74b545d60> setValue:forUndefinedKey:]
报key
找不到的错。 - 分析:模型中的属性和字典的key不一一对应,系统就会调用
setValue:forUndefinedKey:
报错。 - 解决:重写对象的
setValue:forUndefinedKey:
,把系统的方法覆盖,
就能继续使用KVC,字典转模型了。
- 如果不一致,就会调用
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
}
3 字典转模型的方式二:Runtime
- KVC:遍历字典中所有key,去模型中查找有没有对应的属性名
- runtime:遍历模型中所有属性名,去字典中查找
1.思路与步骤
<!--* 思路:利用运行时,遍历模型中所有属性,根据模型的属性名,去字典中查找key,取出对应的值,给模型的属性赋值。-->
<!--* 步骤:提供一个NSObject分类,专门字典转模型,以后所有模型都可以通过这个分类转。-->
2.分类
+ (instancetype)PH_modelWithDict:(NSDictionary *)dict
{
// 创建对应类的对象
id objc = [[self alloc] init];
// runtime:遍历模型中所有成员属性,去字典中查找
// 属性定义在哪,定义在类,类里面有个属性列表(数组)
// 遍历模型所有成员属性
// ivar:成员属性
// class_copyIvarList:把成员属性列表复制一份给你
// Ivar *:指向Ivar指针
// Ivar *:指向一个成员变量数组
// class:获取哪个类的成员属性列表
// count:成员属性总数
unsigned int count = 0;
Ivar *ivarList = class_copyIvarList(self, &count);
for (int i = 0; i < count; i++) {
// 获取成员属性
Ivar ivar = ivarList[i];
// 获取成员名
NSString *propertyName = [NSString stringWithUTF8String:ivar_getName(ivar)];
//成员属性类型
NSString *propertyType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
//获取key
NSString *key = [propertyName substringFromIndex:1];
//获取字典的value
id value = dict[key];
// 给模型的属性赋值
// value:字典的值
// key:属性名
// user:NSDictionary
//** '二级转换'**
// 值是字典,成员属性的类型不是字典,才需要转换成模型
if ([value isKindOfClass:[NSDictionary class]] && ![propertyType containsString:@"NS"]) {
// 需要字典转换成模型
// 转换成哪个类型
// @"@\"User\"" User
NSRange range = [propertyType rangeOfString:@"\""];
propertyType = [propertyType substringFromIndex:range.location + range.length];
// User\"";
range = [propertyType rangeOfString:@"\""];
propertyType = [propertyType substringFromIndex:range.location];
// 字符串截取
// 获取需要转换类的类对象
Class modelClass = NSClassFromString(propertyType);
if (modelClass) {
value = [modelClass PH_modelWithDict:value];
}
}
<!-- 三级转换:NSArray中也是字典,把数组中的字典转换成模型.-->
// 判断值是否是数组
if ([value isKindOfClass:[NSArray class]]) {
//判断对应类有没有实现字典数组转模型数组的协议
if ([self respondsToSelector:@selector(PH_arrayContainModelClass)]) {
// 转换成id类型,就能调用任何对象的方法
id idSelf = self;
// 获取数组中字典对应的模型
NSString *type = [idSelf PH_arrayContainModelClass][key];
// 生成模型
Class classModel = NSClassFromString(type);
NSMutableArray *arrM = [NSMutableArray array];
// 遍历字典数组,生成模型数组
for (NSDictionary *dict in value) {
// 字典转模型
id model = [classModel PH_modelWithDict:dict];
[arrM addObject:model];
}
// 把模型数组赋值给value
value = arrM;
}
}
if (value) {
// kvc赋值:不能传空
[objc setValue:value forKey:key];
}
NSLog(@"%@",key);
NSLog(@"%@,%@",propertyName,propertyType);
}
return objc;
}
3.转换
- (void)viewDidLoad {
[super viewDidLoad];
// 解析
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSArray *dictArr = dict[@"statuses"];
// 设计模型属性代码
NSMutableArray *statuses = [NSMutableArray array];
for (NSDictionary *dict in dictArr) {
// 字典转模型
Status *status = [Status PH_modelWithDict:dict];
[statuses addObject:status];
}
NSLog(@"%@",statuses);
}
网友评论