使用KVC字典转模型的时候,KVC是通过遍历字典中的所有的key去模型中查找有没有对应的属性名,而runtime则是先遍历模型当中的所有的属性名去字典中查找
NSObject+Model.h
#import <Foundation/Foundation.h>
@interface NSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary *)dict;
@end
NSObject+Model.m
#import "NSObject+Model.h"
#import <objc/message.h>
@implementation NSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary *)dict{
// 1.创建对应类的对象
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)];
;
// 获取key
NSString *key = [propertyName substringFromIndex:1];
// user value:字典
// 获取字典的value
id value = dict[key];
// 给模型的属性赋值
// value:字典的值
// key:属性名
// 成员属性类型
NSString *propertyType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
// user:NSDictionary
// 二级转换
// 值是字典,成员属性的类型不是字典,才需要转换成模型
if ([value isKindOfClass:[NSDictionary class]] && ![propertyType containsString:@"NS"]) { // 需要字典转换成模型
//获取到的value的值实际为 @"@\"User\"" 需要截取为User
NSRange range = [propertyType rangeOfString:@"\""];
propertyType = [propertyType substringFromIndex:range.location + range.length];
range = [propertyType rangeOfString:@"\""];
propertyType = [propertyType substringToIndex:range.location];
// 获取需要转换类的类对象
Class modelClass = NSClassFromString(propertyType);
if (modelClass) {
value = [modelClass modelWithDict:value];
}
}
if (value) {
[objc setValue:value forKey:key];
}
}
return objc;
}
@end
模型StatusModel.h
#import <Foundation/Foundation.h>
#import "User.h"
@interface StatusModel : NSObject
@property (nonatomic, assign) NSInteger ID;
@property (nonatomic, strong) NSString *source;
@property (nonatomic, assign) NSInteger reposts_count;
@property (nonatomic, strong) NSArray *pic_urls;
@property (nonatomic, strong) NSString *created_at;
@property (nonatomic, assign) int attitudes_count;
@property (nonatomic, strong) NSString *idstr;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, assign) int comments_count;
@property (nonatomic, strong) User *user;
@property (nonatomic, strong) NSDictionary *retweeted_status;
+ (__kindof StatusModel *)statusWithDict:(NSDictionary *)dict;
@end
StatusModel.m
#import "StatusModel.h"
@implementation StatusModel
+ (StatusModel *)statusWithDict:(NSDictionary *)dict {
StatusModel *model = [[StatusModel alloc] init];
[model setValuesForKeysWithDictionary:dict];
return model;
}
//解决KVC字典转模型,字典里面的id键与系统的id冲突
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
if ([key isEqualToString:@"id"]) {
_ID = [value integerValue];
}
}
@end
解析数据,转模型
- (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) {
StatusModel *status = [StatusModel modelWithDict:dict];
[statuses addObject:status];
}
}
网友评论