国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

詳解Obejective-C中將JSON數據轉為模型的方法

2020-02-19 15:47:01
字體:
來源:轉載
供稿:網友

在我們的日常開發中,我們需要對一些加載的本地數據進行建模,但是在某些情況下,無法成功保存數據也是常有的情況,所以今天武林技術頻道小編詳解Obejective-C中將JSON數據轉為模型的方法。
首先我們還是先要嘗試下使用KVC的方式來解決這個問題
模型如下:

?

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *ID;


JSON數據如下:

?

?

?

{ "title" : "順平侯", "name" : "趙云", "id" : "sph" }, { "title" : "恒侯", "html" : "張飛", "id" : "hh" }, { "title" : "威侯", "html" : "馬超", "id" : "wh" }, { "title" : "剛侯", "html" : "黃忠", "id" : "gh" }, { "title" : "壽亭侯", "html" : "關羽", "id" : "sth" }

從上面的數據對比我們不難發現,因為在OC中的id是關鍵字所有我們使用ID來替代,但是這樣的話就不能直接使用KVC,所以我們需要進行相應的處理來繼續使用我們的KVC轉換模型。代碼如下:
首先在模型.h文件中更新一下代碼,提供一個類方法進行模型轉換:

?

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *ID;

?

+(instancetype) heroDict:(NSDictionary*) dict;


在.m文件中實現該方法

?

?

?


+ (instancetype)itemWithDict:(NSDictionary *)dict
{
??? HeroItem *hero = [[self alloc]init];

?

??? [item setValuesForKeysWithDictionary:dict];
??? return item;
}


程序走到這里就會去模型中遍歷字典當中的所有的key。所以我們要修改的地方也就是這里去重寫KVC中的setValue forKey方法.代碼如下:

?

?

?


- (void)setValue:(id)value forKey:(NSString *)key{
??? //因為已經知道要修改的key所以可以直接判定相等
??? if ([key isEqualToString:@"id"]) {
??????? //進行替換
??????? [self setValue:value forKeyPath:@"ID"];
??? }else{
??????? //拋回父類處理
??????? [super setValue:value forKey:key];
??? }
}


程序修改到這里,基本就可以使用KVC的方法進行轉換。但是如果我們的數據有很多不一致的情況呢?那么就讓我們一起來看下今天的重頭戲runtime來的轉換。
上面的例子的思路是通過遍歷字典當中的key去模型中比對,而我們這次試著遍歷模型,然后去字典中比對響應的key
首先在我們的模型.m里導入我們需要的頭文件

?

?

?


#import <objc/runtime.h>


完成這一步在模型類中就可以使用runtime了,然后我們在.m中創建一個轉換的類方法

?

?

?


+ (instancetype)objcWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict{

?

}


在這個方法中我們需要做的是通過runtime來遍歷模型中的屬性,進行屬性的比對,如果模型中的屬性在字典中不存在,那么就會去updateDict中尋找,如果updateDict字典中存在的話就會進行轉換。objctWithDict:方法更新如下:

?

?

?


(instancetype)objcWithDict:(NSDictionary *)dict updateDict:(NSDictionary *)updateDict{
id objc = [[self alloc] init];
??? // 遍歷模型中屬性
??? unsigned int count = 0;
??? Ivar *ivars = class_copyIvarList(self, &count);
??? for (int i = 0 ; i < count; i++) {
??????? Ivar ivar = ivars[i];
??????? // 屬性名稱
??????? NSString *ivarName = @(ivar_getName(ivar));
??????? ivarName = [ivarName substringFromIndex:1];
??????? id value = dict[ivarName];
??????? // 模型中屬性名對應字典中的key
??????? if (value == nil) {
??????????? if (updateDict) {
??????????? NSString *keyName = updateDict[ivarName];
??????????? value = dict[keyName];
??????????? }
??????? }
??????????? [objc setValue:value forKeyPath:ivarName];
??? }
??? return objc;
}


到了這里轉換已經完成,那么我們更新下heroDict:方法代碼:

?

?

?


+ (instancetype)itemWithDict:(NSDictionary *)dict{
??? //調用方法,updateDict中的數據即為需要替換的數據
??? HeroItem *item = [HeroItem objcWithDict:dict updateDict:@{@"ID":@"id"}];
??? return item;
}


到了這里runtime轉換的方法也完成了。對比兩個方法的話可能明顯會發現第一種方法會比較簡單。但是如果是多個模型的話就需要大量的來重寫setValue:方法了,而第二種方法則可以封裝起來用以適用于各種模型。當然了如果真的是大型項目的話還是比較推薦使用一些非常優秀的第三方框架來處理模型,比如MJ大神的MJExtension使用起來簡單方便,絕對是開發的上上之選了。

?

使用jastor
如果有jastor這個庫,也會方便很多現在就基本的用法做個介紹。

假如我們有如下這么一個類

?

#import <Foundation/Foundation.h>
#import "Jastor.h"

?

@interface DeviceEntity : Jastor

@property (nonatomic,strong) NSNumber *isonline;
@property (nonatomic,strong) NSNumber *isopen;
@property (nonatomic,copy) NSString *brand;

@end

#import "DeviceEntity.h"

@implementation DeviceEntity

@synthesize isopen,isonline,brand;

@end

#import <Foundation/Foundation.h>
#import "Jastor.h"
#import "DeviceEntity.h"

@interface UserDevicesEntity : Jastor

@property (nonatomic,strong) NSNumber *closecount;
@property (nonatomic,strong) NSNumber *opencount;
@property (nonatomic,copy) NSString *success;
@property (nonatomic,strong) NSArray *items;

@end

#import "UserDevicesEntity.h"
#import "DeviceEntity.h"

@implementation UserDevicesEntity

@synthesize closecount,opencount,success,items;

+ (Class) items_class {
??? return [DeviceEntity class];
}

@end


注意這里在定義相應屬性的時候如果是基本類型我們需要用NSNumber來進行包裝,上面的例子也表明了我們可以用數組來做為一個屬性,只在是實現的時候需要告訴它這個數組是什么類型的,你定義的屬性名后跟_class的形式,注意這一點不能搞錯。

?

在調用服務的時候,對方一般都會返回一個json,我們要做的就是根據這個字符串實例化一個NSDictionary出來,然后就可以根據這個NSDictionay實例化相應的模型了,比我們直接解析這個字符串方便多了,代碼如下:

?

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"1",@"isonline",@"1",@"isopen",@"brand1",@"brand", nil];??
DeviceEntity *device = [[DeviceEntity alloc] initWithDictionary:dictionary];


我們可以驗證下,

?

?

?


NSLog(@"device's brand is %@",device.brand);
NSLog(@"device's isonline is %d",[device.isonline intValue]);
NSLog(@"device's isopen is %d",[device.isopen intValue]);


將會打印出

?

2014-02-17 22:36:37.602 objc-grammar-learing[819:f803] device's brand is brand12014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isonline is 12014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isopen is 1

看看是否更方便,當然,上面的模型只是一個非常簡短的章節。一般來說,實際項目中的模型必須比這個更復雜,希望大家能繼續支持武林技術頻道哦!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 高雄县| 托里县| 双峰县| 防城港市| 肇东市| 曲周县| 德庆县| 织金县| 西乡县| 加查县| 和政县| 靖边县| 婺源县| 中阳县| 金塔县| 石棉县| 江山市| 通州区| 肇源县| 德保县| 广宗县| 浠水县| 北宁市| 万全县| 萍乡市| 清原| 调兵山市| 吉林省| 奎屯市| 昌宁县| 广安市| 常德市| 邵阳县| 汽车| 江津市| 清苑县| 石家庄市| 滦南县| 金华市| 德格县| 嘉义县|