你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 詳解Obejective-C中將JSON數據轉為模子的辦法

詳解Obejective-C中將JSON數據轉為模子的辦法

編輯:IOS開發綜合

在我們的平常開辟中須要對加載的一些當地數據例如plist、json等文件中的數據停止模子轉化,而蘋果也為我們供給了一種異常便利的鍵值轉換方法KVC。但是KVC在某些情形下其實不能保留數據的轉換勝利,好比必需包管模子的屬性個數年夜於等於字典個數,也要必需屬性稱號與字典的key雷同等。所以此次我們假定部屬性稱號與字典中的key紛歧致的時刻轉換辦法。
起首我們照樣先要測驗考試下應用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 brand1
2014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isonline is 1
2014-02-17 22:36:37.605 objc-grammar-learing[819:f803] device's isopen is 1

看看是否是便利許多,固然下面只是很簡章的模子,普通來說,真實項目中的模子確定比這龐雜,好比一對一,一對多等等,在官網下面都有響應例子可以參考。

【詳解Obejective-C中將JSON數據轉為模子的辦法】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved