将字典转化为模型,面向模型开发,是在开发中最为常用的功能。利用KVC可以将字典转换为模型,但是前提有三个约束,一个是必须保证模型的属性个数大于等于字典个数,二是属性名称与字典的key必须相同,三是对于模型中的基本数据类型无法转换。
其中第一条与第三条,是其最大的弊端。例如,如果从服务器获取的数据字典,并不想使用所有的键值对。但是在开发中还是必须得全部将对应属性列出,全部进行转换(除非你一个一个写,不使用KVC)。
下面的代码就可以解决上述问题:实现以模型为主,将字典数据进行部分转化,并识别基本数据类型。约束仅仅是要求模型属性名称与字典KEY保持一致(因为底层还是使用KVC);
1 // 2 // NSObject+Value.m 3 // 4 // Created by shunzi 5-10-2014. 5 // Copyright (c) 2014年 shunzi. All rights reserved. 6 // 7 8 #import "NSObject+Value.h" 9 #import <objc/message.h> 10 #import <objc/runtime.h> 11 12 @implementation NSObject (Value) 13 - (void)setValues:(NSDictionary *)values 14 { 15 Class c = [self class]; 16 17 while (c) { 18 // 1.获得所有的成员变量 19 unsigned int outCount = 0; 20 Ivar *ivars = class_copyIvarList(c, &outCount); 21 22 for (int i = 0; i<outCount; i++) { 23 Ivar ivar = ivars[i]; 24 25 // 2.属性名 26 NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)]; 27 28 // 删除最前面的_ 29 [name replaceCharactersInRange:NSMakeRange(0, 1) withString:@""]; 30 31 // 3.取出属性值 32 NSString *key = name; 33 if ([key isEqualToString:@"desc"]) { 34 key = @"description"; 35 } 36 if ([key isEqualToString:@"ID"]) { 37 key = @"id"; 38 } 39 id value = values[key]; 40 if (!value) continue; 41 42 // 4.SEL 43 // 首字母 44 NSString *cap = [name substringToIndex:1]; 45 // 变大写 46 cap = cap.uppercaseString; 47 // 将大写字母调换掉原首字母 48 [name replaceCharactersInRange:NSMakeRange(0, 1) withString:cap]; 49 // 拼接set 50 [name insertString:@"set" atIndex:0]; 51 // 拼接冒号: 52 [name appendString:@":"]; 53 SEL selector = NSSelectorFromString(name); 54 55 // 5.属性类型 56 NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)]; 57 58 if ([type hasPrefix:@"@"]) { // 对象类型 59 objc_msgSend(self, selector, value); 60 } else { // 非对象类型 61 if ([type isEqualToString:@"d"]) { 62 objc_msgSend(self, selector, [value doubleValue]); 63 } else if ([type isEqualToString:@"f"]) { 64 objc_msgSend(self, selector, [value floatValue]); 65 } else if ([type isEqualToString:@"i"]) { 66 objc_msgSend(self, selector, [value intValue]); 67 } else { 68 objc_msgSend(self, selector, [value longLongValue]); 69 } 70 } 71 } 72 73 c = class_getSuperclass(c); 74 } 75 } 76 @end
头文件仅仅包含对此方法的声明,所以不在此粘贴