本篇部落格算是給網路快取打個基礎吧,本篇部落格先給出簡單也是最容易使用的把字典轉成實體類的方法,然後在給出如何使用Runtime來給Model實體類賦值。本篇部落格會介紹一部分,主要是字典的key與Model的屬性名相同時,使用Runtime來進行賦值,下篇部落格會給出字典key的值和Model的名字不同時的解決方案,並給出使用Runtime列印實體類屬性值的方式。
當然你可以使用KVC的setValuesForKeysWithDictionary:方法,下面的方法也是一種解決方案。如果使用setValuesForKeysWithDictionary:方法,則Model基類中必須得重寫下面的方法,不然如果遇到字典的Key和modle的屬性不對應的情況則會出現程式崩潰的情況。
1 2 3 |
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{ } |
iOS開發中的Runtime可謂是功能強大,同時Runtime使用起來也是非常靈活的,今天部落格的內容主要就是使用到一丁點的Runtime的東西。好廢話不多說了進入今天的整體。
一、建立我們的測試工程
在本測試工程中使用不到iOS開發的UI部分,所以我們就建立一個基於系統控制檯的工程,主呼叫程式碼當然是放到main函式中了,Project建立過程如下圖所示,Create new project -> OS X -> Application -> Command Line Tool ->一路next即可
二、建立我們的測試資料
1.首先使用for迴圈建立一個字典,當然字典的key和value在這是有規律的,下面的for迴圈是建立我們的測試資料,如果在有網路請求的狀態下,該測試字典的來源就是你從網路請求的JOSN解析出來的字典,在這兒沒有進行網路請求,因為網路請求不是本篇部落格的重點,所以就使用for迴圈生成一個測試字典以供使用。建立測試字典的程式碼如下,改程式碼的位置放在main函式當中:
1 2 3 4 5 6 7 8 9 10 |
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithCapacity:11]; //建立測試適用的字典 for(int i = 0; i 10; i ++){ NSString *key = [NSString stringWithFormat:@"girl%d", i]; NSString *value = [NSString stringWithFormat:@"我是第%d個女孩", i]; [data setObject:value forKey:key]; } |
上述程式碼生成字典,列印結果如下,可以看出字典是無序的,接下來就將data這個字典作為我們網路請求JSON解析後的字典來使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
2015-07-20 22:33:15.742 BaseModelProject[65321:3224966] data = { girl0 = "我是第0個女孩"; girl1 = "我是第1個女孩"; girl10 = "我是第10個女孩"; girl2 = "我是第2個女孩"; girl3 = "我是第3個女孩"; girl4 = "我是第4個女孩"; girl5 = "我是第5個女孩"; girl6 = "我是第6個女孩"; girl7 = "我是第7個女孩"; girl8 = "我是第8個女孩"; girl9 = "我是第9個女孩"; } |
三、建立data字典對應的實體類
接下來將會建立Data字典對應的實體類,首先將會實現實體類的屬性名和字典的key值一致的情況,然後在下篇部落格中將會實現如何把不同key值的字典轉換成實體類的屬性。
1、首先我們先建立一個實體類,這個實體類要繼承與實體基類,因為一些公用的方法是在實體基類中進行編寫的,如便利構造器,便利初始化方法,把字典轉成Model屬性等方法回被抽象到這個基類當中。建立實體類如下圖所示,建立類的時候選中建立的基類即可:
2. 這個實體類的命名為:BeautifulGirlModel,下面是BeautifulGirlModel中的屬性,屬性的名字和字典key的值相同,如下所示,BaseModelObject是之前建立的基類,BaseModelObject繼承與NSObject即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// // BeautifulGirlModel.h // BaseModelProject // // Created by Mr.LuDashi on 15/7/20. // Copyright (c) 2015年 ludashi. All rights reserved. // #import "BaseModelObject.h" @interface BeautifulGirlModel : BaseModelObject @property (nonatomic, copy) NSString *girl0; @property (nonatomic, copy) NSString *girl1; @property (nonatomic, copy) NSString *girl2; @property (nonatomic, copy) NSString *girl3; @property (nonatomic, copy) NSString *girl4; @property (nonatomic, copy) NSString *girl5; @property (nonatomic, copy) NSString *girl6; @property (nonatomic, copy) NSString *girl7; @property (nonatomic, copy) NSString *girl8; @property (nonatomic, copy) NSString *girl9; @property (nonatomic, copy) NSString *girl10; @end |
四、實現實體基類中的方法
實體基類中的方法是從各個Model中抽象出來的並且可以重複利用的部分,在實體基類的方法中大致包括:生成getter方法,生成setter方法,獲取Model類的屬性,把字典的值賦給對應的Model, 動態的呼叫getter方法對實體類的屬性值進行遍歷。本篇部落格中回給出一部分,剩下的一部分會在以後的部落格中陸續給出。
1.根據Key值生成set方法
首先要編寫的方法是傳入一個字串,然後返回該字串所對應屬性的setter方法。這個方法其實很簡單的,就是把對應的字串的首字母大寫並且拼接上set關鍵字,再生產SEL並返回,該方法的具體實現如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
#pragma mark -- 通過字串來建立該字串的Setter方法,並返回 - (SEL) creatSetterWithPropertyName: (NSString *) propertyName{ //1.首字母大寫 propertyName = propertyName.capitalizedString; //2.拼接上set關鍵字 propertyName = [NSString stringWithFormat:@"set%@:", propertyName]; //3.返回set方法 return NSSelectorFromString(propertyName); } |
2.把字典傳入到方法中,並把字典的值賦給相應實體類的屬性,該方法需要呼叫上述方法來生成setter方法,通過setter方法把字典的Value賦值給實體類對應的屬性,程式碼如下,下面程式碼中的註釋還是比較詳細的,具體細節就參考下面註釋的內容了。通過呼叫這個方法就可以把字典的值賦給對應的實體類的屬性,呼叫這個方法的前提是要求字典的key與實體類的屬性名必須相同。有的小夥伴會問如果不一樣該怎麼做呢?這個問題到下篇部落格中在進行介紹。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
/************************************************************************ *把字典賦值給當前實體類的屬性 *引數:字典 *適用情況:當網路請求的資料的key與實體類的屬性相同時可以通過此方法吧字典的Value * 賦值給實體類的屬性 ************************************************************************/ -(void) assginToPropertyWithDictionary: (NSDictionary *) data{ if (data == nil) { return; } ///1.獲取字典的key NSArray *dicKey = [data allKeys]; ///2.迴圈遍歷字典key, 並且動態生成實體類的setter方法,把字典的Value通過setter方法 ///賦值給實體類的屬性 for (int i = 0; i < dicKey.count; i ++) { ///2.1 通過getSetterSelWithAttibuteName 方法來獲取實體類的set方法 SEL setSel = [self creatSetterWithPropertyName:dicKey[i]]; if ([self respondsToSelector:setSel]) { ///2.2 獲取字典中key對應的value NSString *value = [NSString stringWithFormat:@"%@", data[dicKey[i]]]; ///2.3 把值通過setter方法賦值給實體類的屬性 [self performSelectorOnMainThread:setSel withObject:value waitUntilDone:[NSThread isMainThread]]; } } } |
3.接下來就是開始編寫實體類的入口了,也就是便利初始化方法和便利構造器。並在標頭檔案中留出介面,下面先給出便利初始化方法然後在給出便利構造器。
(1)下面的程式碼是實體類的便利初始化方法,當然是例項方法,該方法需要傳入一個字典,這個字典中的key就是該實體類的屬性名,值就是要給該實體類的屬性賦的值。並且返回該實體類的例項,簡單的說就是呼叫-(void) assginToPropertyWithDictionary: (NSDictionary *) data方法,具體程式碼如下:
1 2 3 4 5 6 7 8 9 |
- (instancetype)initWithDictionary: (NSDictionary *) data{ { self = [super init]; if (self) { [self assginToPropertyWithDictionary:data]; } return self; } } |
(2)下面將要給出便利構造器,當然便利構造器是類方法,並且返回該類的一個例項。用大白話說,便利構造器就是分配記憶體後呼叫便利初始化方法然後返回該物件的例項,下方是實體類對應的便利構造器:
1 2 3 |
+ (instancetype)modelWithDictionary: (NSDictionary *) data{ return [[self alloc] initWithDictionary:data]; } |
五、測試上面的程式碼
上面執行這麼多了得執行一下程式碼看一下結果吧。因為我們這是基於系統的控制檯程式,所以我們需要在main函式中進行呼叫我們編寫的方法,需要把我們上面生成的測試字典傳入到實體類的構造器中,並且獲取實體類的一個例項。該獲取的實體類的例項中的屬性就已經被賦值上了傳入的字典的值。具體呼叫方法如下所示。
1 2 |
BeautifulGirlModel *beautifulGirl = [BeautifulGirlModel modelWithDictionary:data]; NSLog(@"%@", beautifulGirl.girl0); |
執行結果如下:
使用setValuesForKeysWithDictionary方法賦值,測試程式碼如下:
1 2 |
BeautifulGirlModel *beautifulGirl = [[BeautifulGirlModel alloc] init]; [beautifulGirl setValuesForKeysWithDictionary:data]; |
最後給出最笨的賦值方法,也是最容易學會的賦值方法,不過這種方式維護起來回不太方便,而且大部分做的都是體力活的,例項如下:
1 2 3 4 5 6 7 8 9 |
BeautifulGirlModel *beautifulGirl1 = [[BeautifulGirlModel alloc] init]; beautifulGirl1.girl0 = data[@"girl0"]; beautifulGirl1.girl1 = data[@"girl1"]; beautifulGirl1.girl2 = data[@"girl2"]; beautifulGirl1.girl3 = data[@"girl3"]; beautifulGirl1.girl4 = data[@"girl4"]; beautifulGirl1.girl5 = data[@"girl5"]; beautifulGirl1.girl6 = data[@"girl6"]; beautifulGirl1.girl7 = data[@"girl7"]; |
今天部落格中的內容就到這吧,剩下的內容會在下一篇部落格中介紹到,下一篇部落格的內容的乾貨要比這篇部落格要足一些。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!