上篇文章寫了,runtime實現一級轉換的代碼,但是我們開發中二級轉換也是很常用的,下面我就講解一下二級轉換的思路和代碼的實現:
二級轉換是指:模型中有另外的模型屬性,需要將模型中的字典屬性轉換為模型,再賦值給模型屬性(如果覺得有點繞,可以多讀兩遍??)
實現邏輯(ivar指通過runtime獲得的成員變量)
滿足以下條件,才需要使用二級轉換:
①一級字典轉模型時,根據key(ivar的名稱)得到value為NSDictionary類,這樣這個value才有可能需要轉為模型保存
②同時還需要滿足成員變量的類型(ivar的類型)不是NSDictionary類,因為有些模型可能就需要是字典屬性,而非模型屬性
二級轉換實現代碼如下:
#import "NSObject+Model.h"
#import <objc/message.h>
@implementation NSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary *)dict
{
id objc = [[self alloc]init];
// runtime:遍歷模型中的屬性,去字典中取出對應的value,給屬性賦值
// 1.獲取模型中的所有屬性 (我們取成員變量,更加嚴謹而且是copy)
// ivar:成員變量 property:屬性
// class:獲取哪個類的成員變量列表 *count: 存放成員變量的地址
uint count = 0;
Ivar *ivarList = class_copyIvarList(self, &count);
// 遍歷成員變量數組
for (int i =0; i < count; i++) {
// 1.獲取成員變量
Ivar ivar = ivarList[i];
// 2.獲取成員變量名稱
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 獲取成員變量類型
NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
type = [type stringByReplacingOccurrencesOfString:@"@\"" withString:@""];
type = [type stringByReplacingOccurrencesOfString:@"\"" withString:@""];
// 3.從字典中取出對應的value
NSString *key = [ivarName substringFromIndex:1];
id value = dict[key];
//只有value是字典才有可能需要轉換 并且成員變量類型不是字典類型,才需要二級轉換
if([value isKindOfClass:[NSDictionary class]] && ![type containsString:@"NS"]){
// 獲取類對象
Class className = NSClassFromString(type);
// 字典轉模型
value = [className modelWithDict:value];
}
// 4.給模型中對于屬性賦值
if (value) {
[objc setObject:value forKey:key];
}
}
return objc;
}
@end
使用動態copy成員變量而不是屬性,是為了讓代碼實現的更加嚴謹,希望此片文章能給你帶來點幫助.
對于三級轉換,我覺得就比較復雜了,是指字典里面包含存放模型的數組,還是使用第三方框架,更加方便.
但是如果只需要進行二級轉換以內,我覺得大家可以添加我寫的這個分類,使用更快捷方便.