利用Runtime實現(xiàn)字典轉(zhuǎn)模型

參考自:http://www.reibang.com/p/836f07bb468e

  • Runtime 是一種面向?qū)ο缶幊陶Z言的運行環(huán)境
  • OC最主要的特點就是在程序運行時酿雪,以發(fā)送消息的方式調(diào)用方法(也就是常說的OC是基于運行時的)


一句話概括:通過 Runtime 獲取 model 的屬性列表召川,然后遍歷字典中的 key,如果屬性列表中包含這個 key 則通過 KVC 把字典中對應的 value 賦值到 model 的屬性腕唧。

字典轉(zhuǎn)模型核心算法思路.png

為什么要利用 Runtime 來進行字典轉(zhuǎn)模型:

  • 如果是通過在 model 的 .m 中添加字典轉(zhuǎn)模型的方法,那么枢里,當真正在開發(fā)項目的時候探越,由于有各種不同的 model邢滑,就需要給每個 model 的 .m 都加上字典轉(zhuǎn)模型的方法腐螟。這個方法的思路都是一樣的,只是因為 model 中的屬性略有變化。
  • 所以遭垛,我們可以通過為 NSObject 添加一個分類 (因為所有的類(NSProxy 除外)都繼承自 NSObjec)尼桶,利用 Runtime 實現(xiàn)字典轉(zhuǎn)模型的方法,讓所有的 model 都可以使用锯仪。
首先獲取屬性列表泵督。
const char *key = "key";

+ (NSArray *)getPropertyArr {
    
    // 獲取關(guān)聯(lián)對象
    NSArray *proArr = objc_getAssociatedObject(self, key);
    if (proArr) return proArr; // 如果有值,直接返回
    
    // 調(diào)用運行時方法庶喜,獲取類的屬性列表
    /* 成員變量:
     * class_copyIvarList(__unsafe_unretained Class cls, unsigned int *outCount)
     * 方法:
     * class_copyMethodList(__unsafe_unretained Class cls, unsigned int *outCount)
     * 屬性:
     * class_copyPropertyList(__unsafe_unretained Class cls, unsigned int *outCount)
     * 協(xié)議:
     * class_copyProtocolList(__unsafe_unretained Class cls, unsigned int *outCount)
     */
    
    unsigned int count = 0;
    
    // retain, creat, copy 需要release
    objc_property_t *property_List = class_copyPropertyList([self class], &count);
    NSMutableArray *mtArr = [NSMutableArray array];
    
    // 遍歷屬性列表, 獲取屬性名稱
    for (int i = 0; i < count; i ++) {
        
        objc_property_t pro = property_List[i];
        const char *proName_c = property_getName(pro);
        NSString *proName = [NSString stringWithCString:proName_c encoding:NSUTF8StringEncoding];
        [mtArr addObject:proName];
    }
    
    // 設(shè)置關(guān)聯(lián)對象
     objc_setAssociatedObject(self, key, mtArr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    free(property_List);
    return mtArr;
}

關(guān)鍵步驟:

  • 1.NSArray *proArr = objc_getAssociatedObject(self, key);
    如果在程序運行的時候, 模型對象的屬性是不會發(fā)生變化的, 我們在利用這個函數(shù)如果能獲取到關(guān)聯(lián)對象的屬性列表, 就不用再走下面的代碼去利用運行時再去獲取屬性列表了

  • 2.objc_property_t *property_List = class_copyPropertyList([self class], &count);
    這句代碼就是真正的利用運行時獲取屬性列表, 這個屬性列表是 C 的結(jié)構(gòu)體指針數(shù)組,我們必須將其遍歷,并利用另外一個函數(shù)將取出結(jié)構(gòu)體指針所指向的結(jié)構(gòu)體中的 C 字符串,也就是屬性名稱

  • 3.const char *proName_c = property_getName(pro);
    獲得C字符串后,我們只需要將其轉(zhuǎn)換為 OC 字符串,加到可變數(shù)組中即可

  • 4.objc_setAssociatedObject(self, key, mtArr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    設(shè)置屬性列表關(guān)聯(lián), 就是把已經(jīng)生成好的屬性列表通過 key 與當前類關(guān)聯(lián)到一起小腊,需要用的時候通過 key 獲取。

獲取到屬性列表后久窟,進行字典轉(zhuǎn)模型秩冈。
+ (instancetype)modelWithDic:(NSDictionary *)dic {
    
    // 實例化當前對象
    id objc = [[self alloc] init];
    
    // 獲取self 的屬性列表
    NSArray *proArr = [self getPropertyArr];
    
    // 遍歷字典
    [dic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
       
        // 判斷 屬性列表中是否包含這個 key
        if ([proArr containsObject:key]) {
            
            // 如果包含通過 KVC 賦值到 model
            [objc setValue:obj forKey:key];
        }
    }];
    return objc;
}

現(xiàn)在就可以定義一個模型,進行字典轉(zhuǎn)模型了

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSDictionary *dic = @{
                          @"name": @"小李",
                          @"title": @"司機"
                          };
    Person *personModel = [Person modelWithDic:dic];
    
    NSLog(@"%@ --- %@", personModel.name, personModel.title);
    
}
轉(zhuǎn)換結(jié)果

這就是一些第三方框架,例如 YYModel,MJExtension等的核心算法斥扛,希望在用的時候能明白其中的原理入问。
代碼地址:https://github.com/zhifanYoung/json2model-Demo.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市稀颁,隨后出現(xiàn)的幾起案子芬失,更是在濱河造成了極大的恐慌,老刑警劉巖匾灶,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棱烂,死亡現(xiàn)場離奇詭異,居然都是意外死亡阶女,警方通過查閱死者的電腦和手機颊糜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秃踩,“玉大人衬鱼,你說我怎么就攤上這事°狙睿” “怎么了馁启?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長芍秆。 經(jīng)常有香客問我,道長翠勉,這世上最難降的妖魔是什么妖啥? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮对碌,結(jié)果婚禮上荆虱,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好怀读,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布诉位。 她就那樣靜靜地躺著,像睡著了一般菜枷。 火紅的嫁衣襯著肌膚如雪苍糠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天啤誊,我揣著相機與錄音岳瞭,去河邊找鬼。 笑死蚊锹,一個胖子當著我的面吹牛瞳筏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播牡昆,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姚炕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丢烘?” 一聲冷哼從身側(cè)響起柱宦,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铅协,沒想到半個月后捷沸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡狐史,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年痒给,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骏全。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡苍柏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姜贡,到底是詐尸還是另有隱情试吁,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布楼咳,位于F島的核電站熄捍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏母怜。R本人自食惡果不足惜余耽,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望苹熏。 院中可真熱鬧碟贾,春花似錦币喧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至朱巨,卻和暖如春史翘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔬崩。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工恶座, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沥阳。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓跨琳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親桐罕。 傳聞我的和親對象是個殘疾皇子脉让,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 對于從事 iOS 開發(fā)人員來說,所有的人都會答出【runtime 是運行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,721評論 7 64
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉功炮,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,715評論 0 9
  • 實現(xiàn)二級字典轉(zhuǎn)模型
    Young_Blood閱讀 189評論 0 0
  • 思緒翻涌溅潜,卻不知如何下筆。 夜涼如水薪伏,星光闌珊滚澜。 回憶中的那個少女,爽朗嫁怀,愛笑设捐。 時光似無情的流水,匆匆而去塘淑。 我...
    時光薄暮閱讀 160評論 0 0
  • 第1次美好分享 |每個人都獨一無二 |每一段向上生長都閃閃發(fā)光 亞平存捺,來自廊坊的北方大妞槐沼,烏克蘭留學6年,現(xiàn)在生活...
    Emma美食瑜伽和愛閱讀 712評論 0 1