现在大家提起字典转模型,都会想到使用MJExtension第三方库.这那里面封装了很多的功能,确实非常方便好用, 但我现在的需求仅仅只是从json解析过来的数据传值给我定义的modal,不需要用那么多功能,自然也就不想拖那么多多余的类进我的工程里面. 所以我就自定义了一个字典转模型的分类实现我这一简单的功能:
解决的问题:当json里的字段和Modal里的属性名一致时,可以直接用: - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues; 当不一致,如后台又加了字段,删或改了字段, 再用那个方法你运行就直接崩溃了.我定义的这个分类就是解决这个崩溃的问题!
#pragma mark --取得类中的所以属性名
- (NSMutableArray *)getProperties:(Class)class
{
unsigned int count;
objc_property_t *properties = class_copyPropertyList(class, &count);
NSMutableArray * propertyArray = [NSMutableArray array];
for (int i = 0; i<count; i++) {
// objc_property_t 属性类型
objc_property_t property = properties[i];
// 获取属性的名称 C语言字符串
const char *cName = property_getName(property);
// 转换为Objective C 字符串
NSString *nameStr = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
[propertyArray addObject:nameStr];
}
return propertyArray;
}
#pragma mark -- 通过字符串来创建该字符串的Setter方法,并返回
- (SEL) creatSetterWithPropertyName: (NSString *) propertyName{
// 只把首字母变成大写,其它的不变
NSString * firstStr = [propertyName substringToIndex:1];
NSString * secondStr = [propertyName substringFromIndex:1];
//1.首字母大写
firstStr = firstStr.capitalizedString;
//2.拼接上set关键字
propertyName = [NSString stringWithFormat:@"set%@%@:", firstStr,secondStr];
//3.返回set方法
return NSSelectorFromString(propertyName);
}
#pragma mark --利用传入的字典给类属性赋值
- (instancetype) assginToPropertyWithDictionary: (NSDictionary *) data
{
if (data == nil) {
return nil;
}
// 获取所有的属性值
NSMutableArray * array = [self getProperties:[self class] ];
NSMutableDictionary * valueDictionary = [NSMutableDictionary dictionary];
NSMutableArray * propertyArray = [NSMutableArray array];
for (NSString * string in array) {
if ([[data allKeys] containsObject:string]) {
[valueDictionary setObject:data[string] forKey:string];
}else{
[propertyArray addObject:string];
}
}
///2.循环遍历字典key, 并且动态生成实体类的setter方法,把字典的Value通过setter方法
///赋值给实体类的属性
for (int i = 0; i < valueDictionary.count; i ++) { //当字典中键值比较多时.
NSString * propertyStr = [valueDictionary allKeys][i];
///2.1 通过getSetterSelWithAttibuteName 方法来获取实体类的set方法
SEL setSel = [self creatSetterWithPropertyName:propertyStr];
if ([self respondsToSelector:setSel]) {
///2.2 获取字典中key对应的value
NSString *value = [NSString stringWithFormat:@"%@", valueDictionary[propertyStr]];
///2.3 把值通过setter方法赋值给实体类的属性
[self performSelectorOnMainThread:setSel
withObject:value
waitUntilDone:[NSThread isMainThread]];
}
}
for (int i = 0; i<propertyArray.count; i++) { //当类属性比较多时
SEL setSel = [self creatSetterWithPropertyName:propertyArray[i]];
if ([self respondsToSelector:setSel]) {
///2.2 获取字典中key对应的value
NSString * str = @"";
NSString *value = [NSString stringWithFormat:@"%@", str];
///2.3 把值通过setter方法赋值给实体类的属性
[self performSelectorOnMainThread:setSel
withObject:value
waitUntilDone:[NSThread isMainThread]];
}
}
return self;
}
建个NSObject的分类,定一个类方法.
+ (instancetype)valueWithDictionary:(NSDictionary *)dict
{
return [[self alloc] assginToPropertyWithDictionary:dict];
}
搞定,针对模型类属性与json字段不一致的情况,直接将这个分类拖进去,调用类方法,既能传值,又不会导致崩溃的情况!