runtime 字典轉(zhuǎn)模型,主要是利用runtime的class_copyIvarList方法來獲取到類中的所有的成員變量,字典轉(zhuǎn)模型的情況有以下幾種情況:
1、json對象中包含對象,這種情況下,如果model定義的屬性名和json中對象的參數(shù)一致,則不需要做多余的處理,否則要對model中定義的屬性名進(jìn)行指定,已和json數(shù)據(jù)中的參數(shù)一致
2、json對象中包含數(shù)組,數(shù)組里面包含其他對象;這種情況下,要指定數(shù)組里面的對象對應(yīng)的model模型,類似于YYModel里面的modelContainerPropertyGenericClass方法
例如:
例如圖一和圖二,圖一中定義的birthday和圖二中的birth是表達(dá)一個(gè)意思,但是名稱不一致,這時(shí)就需要將birthday指定成birth
圖一定義了一個(gè)User屬性對象user,這個(gè)user和圖二的user是一致的,所以即使是對象,也不需要做其他操作
其余注意的地方會在具體的代碼中實(shí)現(xiàn)出來
//? ? 創(chuàng)建當(dāng)前類的實(shí)例變量
? ? idobjc = [[selfalloc]init];
? ? ididself =self;
? ? unsignedintcount;
//? ? 獲取類中所有的屬性變量
? ? Ivar* ivarList =class_copyIvarList(self, &count);
//? ? 遍歷所有的屬性變量
? ? for(inti =0; i < count; i ++) {
//? ? ? ? 根據(jù)下標(biāo)獲取成員變量
? ? ? ? Ivarivar = ivarList[i];
//? ? ? ? 獲取成員變量名稱
? ? ? ? NSString * name = [NSString stringWithUTF8String:ivar_getName(ivar)];
//? ? ? ? 獲取當(dāng)前的成員變量的類型
? ? ? ? NSString * ivarType = [NSString ?stringWithUTF8String:ivar_getTypeEncoding(ivar)];
//? ? ? ? 對類型type進(jìn)行處理
? ? ? ? ivarType = [ivarTyp estringByReplacingOccurrencesOfString:@"\"" withString:@""];
? ? ? ? ivarType = [ivarType stringByReplacingOccurrencesOfString:@"@" withString:@""];
//? ? ? ? 處理獲取到的變量名——>對獲取的name進(jìn)行截取(name第一位為_)
? ? ? ? NSString * key = [name substringFromIndex:1];
//? ? ? ? 當(dāng)字典中的字段和定義屬性名不一致的時(shí)候,需要對key進(jìn)行轉(zhuǎn)換,以取得字典中的數(shù)據(jù)
? ? ? ? ididkey = [idself modelCustomPropertyMapper][key];
? ? ? ? if(idkey ==nil) {
? ? ? ? ? ? idkey = key;
? ? ? ? }
//? ? ? ? 根據(jù)key值獲取字典中對應(yīng)的value
? ? ? ? id value = dict[idkey];
if(value) {
? ? ? ? ? ? [objc setValue:value forKey:key];
? ? ? ? }}
上述代碼中最主要的幾點(diǎn)就是runtime里面的幾個(gè)主要的方法來實(shí)現(xiàn):
1、class_copyIvarList方法,這個(gè)方法有兩個(gè)參數(shù),一個(gè)是Class參數(shù),傳入的是想獲取的model類,另外一個(gè)為unsigned int類型,會返回當(dāng)前類所有的屬性變量的個(gè)數(shù)
2、ivar_getName 這個(gè)是獲取屬性變量名的名稱,例如_user
3、ivar_getTypeEncoding 這個(gè)方法是獲取當(dāng)前屬性名的類型,返回的是:@"\User\"
針對json中的字段和定義的屬性不一致的時(shí)候,這時(shí)就需要指定屬性名為json中的字段
modelCustomPropertyMapper方法的實(shí)現(xiàn)是返回一個(gè)字典,字典類似于@{@"birthday":@"birth"},其中birthday是自己定義的屬性,birth是json中對應(yīng)的字段,指定birthday為birth后,則可以在json中獲取到對應(yīng)的數(shù)據(jù)
二、下面是針對model對象中包含model對象
//? ? ? ? 判斷當(dāng)前的value是不是字典
? ? ? ? if([value isKindOfClass:[NSDictionary class]] && ![ivarType
hasPrefix:@"NS"]) {
? ? ? ? ? ? //? ? ? ? 獲取type的類型
? ? ? ? ? ? ClassmethodClass =NSClassFromString(ivarType);
//? ? ? ? ? ? 如果typeClass存在,則
? ? ? ? ? ? if(methodClass) {
? ? ? ? ? ? ? ? value = [methodClass modelWithDict:value];
? ? ? ? ? ? }
? ? ? ? }
上述代碼會獲取到當(dāng)前model對應(yīng)的類型,如果當(dāng)前這個(gè)model來存在,則進(jìn)行賦值
三、model對象中包含數(shù)組,這個(gè)時(shí)候就需要指定數(shù)組中對應(yīng)model模型,例如:Person對象中,定義一個(gè)users數(shù)組,users數(shù)組里面包含的對象類型是User這個(gè)時(shí)候需要在方法arrayContainModelClass中指定:
這個(gè)處理好之后,就可以處理這種情況了:
//? ? ? ? 判斷當(dāng)前的value 是不是數(shù)組
? ? ? ? if ([value isKindOfClass:[NSArray class]]) {
//? ? ? ? ? ? 獲取到數(shù)組value的type
? ? ? ? ? ? NSString*type = [idselfarrayContainModelClass][key];
//? ? ? ? ? ? 生成模型
? ? ? ? ? ? ClassmethodClass =NSClassFromString(type);
? ? ? ? ? ? NSMutableArray * mulary= [NSMutableArray array];
//? ? ? ? ? ? 遍歷字典數(shù)組,生成模型數(shù)組
? ? ? ? ? ? for(NSDictionary* dic in value) {
//? ? ? ? ? ? ? ? 字典轉(zhuǎn)模型
? ? ? ? ? ? ? ? idmodel = [methodClass modelWithDict:dic];
? ? ? ? ? ? ? ? [mulary addObject:model];
? ? ? ? ? ? }
? ? ? ? ? ? value = mulary;
? ? ? ? }
上述代碼理解起來不難,主要是遍歷數(shù)組,然后保存到value中,賦值