字典转模型方法实现(利用kvc可快速实现)
// 模型方法
+ (instancetype)statusWithDict:(NSDictionary *)dict{
// 创建模型
Status *s = [[self alloc] init];
// 字典value转模型属性保存
[s setValuesForKeysWithDictionary:dict];
return s;
}
- 但是有时字典一些属性我们不需要时, 即我们模型的属性与字典的key不一一匹配时, 使用该方法会报错
- setValue: forUndefinedKey:报该犯法错误, 但是我们仅仅是重写该方法即可
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
// 什么都不做,覆盖系统方法
}
- 该方法缺点在于仅仅只是适用于转换一级模型, 当有多级模型嵌套时则不适用
问题思考:
-
当字典的key与模型属性不匹配时
-
多级模型嵌套
怎么快速实现字典转模型?
在这方面MJExtension就做的比较好;
- MJExtension:字典转模型,可以不用与字典中属性一一对应
- 其底层实现是利用runtime,遍历模型中有多少个属性,直接去字典中取出对应value,给模型赋值;
代码实现:
// status模型头文件
#import <Foundation/Foundation.h>
@class User;
@interface Status : NSObject
@property (nonatomic, strong) NSString *source;
@property (nonatomic, assign) NSInteger reposts_count;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, assign) NSInteger comments_count;
// status模型中嵌套一个User模型
@property (nonatomic, strong) User *user;
@end
// USer模型头文件
#import <Foundation/Foundation.h>
@interface User : NSObject
@property (nonatomic, assign) BOOL vip;
@property (nonatomic, strong) NSString *name;
@end
既然模型继承于NSobject,我们可以给NSObiect抽取一分类方便以后使用;
方法的核心时:利用runtime实现运行时,根据模型的属性去字典获取对应key的value;
NSObject分类
#import <Foundation/Foundation.h>
@interface NSObject (Model)
// 传入字典获取模型
+ (instancetype)modelWithDict:(NSDictionary *)dict;
@end
#import "NSObject+Model.h"
#import <objc/message.h>
@implementation NSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary *)dict
{
// 创建一个模型对象(由于不知道模型具体的类型,选择使用id)
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 *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// 注:此时输出的type == @"@\"User\"";需转换为@"User"
// @"@\"User\"" -> @"User"
type = [type stringByReplacingOccurrencesOfString:@"@\"" withString:@""];
type = [type stringByReplacingOccurrencesOfString:@"\"" withString:@""];
// 成员变量名称转换key _user===>user
NSString *key = [ivarName substringFromIndex:1];
// 从字典中取出对应value dict[@"user"] -> 字典
id value = dict[key];
// 二级转换
// 当获取的value为字典时,且type是模型
// 即二级模型
if ([value isKindOfClass:[NSDictionary class]] && ![type containsString:@"NS"]) {
// 获取对应的类
Class className = NSClassFromString(type);
// 字典转模型
value = [className modelWithDict:value];
}
// 给模型中属性赋值
if (value) {
[objc setValue:value forKey:key];
}
}
return objc;
}
@end
当封装好类后, 直接调用该方法即可实现多级模型嵌套;以及模型属性与字典的key不匹配问题:
// 字典转模型:把字典中所有value保存到模型中
Status *s = [Status modelWithDict:dict];
总结:
-
本文的核心:根据模型属性去字典中取对应key的value;并不是直接使用字典给模型赋值
-
对于多级模型嵌套, 应逐层赋值
-
封装一个独立的分类,实现复用
网友评论