將字典轉化為模型袁余,面向模型開發(fā)衣陶,是在開發(fā)中最為常用的功能柄瑰。利用KVC可以將字典轉換為模型,但是前提有三個約束剪况,一個是必須保證模型的屬性個數大于等于字典個數教沾,二是屬性名稱與字典的key必須相同,三是對于模型中的基本數據類型無法轉換译断。
其中第一條與第三條授翻,是其最大的弊端。例如孙咪,如果從服務器獲取的數據字典堪唐,并不想使用所有的鍵值對。但是在開發(fā)中還是必須得全部將對應屬性列出翎蹈,全部進行轉換(除非你一個一個寫淮菠,不使用KVC)。
下面的代碼就可以解決上述問題:實現以模型為主荤堪,將字典數據進行部分轉化合陵,并識別基本數據類型。約束僅僅是要求模型屬性名稱與字典KEY保持一致(因為底層還是使用KVC);
//
2 // NSObject+Value.m
3 //
4 // Created by Apple 2-2-2016.
5 // Copyright (c) 2016年 Apple. 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