在iOS開發(fā)當中model類是必不可少的,將json轉化為model也是必不可少的一步⊥锱福基本的字典轉模型基本上是下面這種情況
- (id)initWithDictionary:(NSDictionary *)dict{
if (self = [super init]) {
self.name = dict[@"name"];
self.age = dict[@"age"];
self.intro = dict[@"intro"];
self.friends = dict[@"friends"];
}
return self;
}
這樣做的好處就是簡單明了,適合初學者悍缠。但是應用在項目中就不是那么理想了卦绣,一個項目動輒幾十個model一個Model的屬性也很多這樣一條條賦值顯然不明智。
利用runtime進行字典轉模型
runtime的基礎只是不做過多介紹可自行翻文檔進行查閱飞蚓,下面我們就利用runtime來查找自身變量從而進行賦值操作
Ivar *ivarList = class_copyIvarList(cls, &count);
class_copyIvarList獲得的是Ivar數(shù)組滤港,即當前對象的變量列表,然后我們通過便利數(shù)組可以獲得每條變量的信息
利用ivar_getName可以獲得變量名趴拧,利用:ivar_getTypeEncoding可以獲得變量類型信息需要注意的是property聲明的屬性會在變量名前面加_ 下劃線溅漾,在setValue:forKey 的時候需要截掉這個下劃線
然后就是賦值過程
if ([[dict allKeys] containsObject:key]) {
id value = dict[key];
/*
在OC里指針的類型與聲明的類型無關,指向什么類型才是它的類型著榴,舉個例子
NSString *aString = [@{@"key":@4} objectForKey:@"key"];
NSLog(@"%@========",[string substringFromIndex:0]);
這兩行代碼會報錯添履,錯誤原因是[__NSCFNumber substringFromIndex:]: unrecognized selector sent to instance 也就是說這里的aString實際上是NSNumber類型的
在網(wǎng)絡請求中,我們接收到的數(shù)字類的數(shù)據(jù)類型往往不一定會是string類型的 但是我們希望用string來
處理它脑又,所以這里需要做強制的初始化確保類型的正確
*/
if ([ivarType isEqualToString:@"@\"NSString\""]) {
NSString *stringValue = [NSString stringWithFormat:@"%@",value];
if (!JK_IS_STR_NIL(stringValue)) {
[model setValue:value forKey:key];
}else{
[model setValue:@"" forKey:key];
}
//對于字典類型的數(shù)據(jù)在業(yè)務中可能用一個model來接收
}else if ([value isKindOfClass:NSClassFromString(@"NSDictionary")]&&![ivarType isEqualToString:@"@\"NSDictionary\""]){
Class objClass = NSClassFromString([ivarType substringWithRange:NSMakeRange(2, ivarType.length-3)]);
NSObject *obj = [objClass modelWithDict:value];
[model setValue:obj forKey:key];
}else{
if (value) {
[model setValue:value forKey:key];
}
}
根據(jù)自己的業(yè)務需要進行相應的封裝暮胧,在我自己的業(yè)務中因為我習慣性用NSString接收所有的數(shù)據(jù)類型,所以我會將接收到的數(shù)據(jù)類型都初始化成string防止出錯
另外在如果需要在實體中將另一個類作為屬性问麸,我們可以通過NSClassFromString來生成這個類然后重新進行一次modelWithDic操作就可以啦往衷。
這樣基本功能就有了,我們把上述代碼寫進NSObject擴展里就可以擴展出字典轉模型的方法了 附上git地址