利用Runtime寫一個JSON轉Model的工具

發表於2016-07-22

前言


好久沒有寫過新文章了,最近一直在忙工作的事情,我的新浪微博開源專案也停止了一週時間,目前完成了60%,就先寫一篇關於JSON轉Model的文章和大家聊聊天吧,為什麼會寫一個這個小工具呢,請看文末?


核心方法Runtime的介紹


1. Runtime是什麼?

顧名思義:Runtime就是執行時的意思,是系統在執行時的一些機制,其中最主要的就是訊息機制,舉個常用的例子,在物件導向程式設計的語言中,萬物皆物件,物件如何呼叫方法呢,
[target excuteSEL],需要一個物件,需要一個方法名,系統在執行時會自動轉換成以下的形式:
objc_msgSend(target,@selector(excuteSEL:))

關於Runtime的詳細介紹,網上有很多,這裡就不做過多描述了。


2.Runtime的常見用法

注:使用時需要#import

* 1 方法替換(黑魔法)

舉個例子來說明一下:
將呼叫A方法替換為呼叫B方法

* 2 獲取物件的屬性和方法

注:獲取物件的屬性,這個方法在JSON轉Model可以說是核心方法了
舉例說明:


* 2 設定物件關聯

定義:關聯是指把兩個物件相互關聯起來,使其中的一個物件作為另外一個物件的一部分
再舉個例子,我在物件中定義了一個屬性

Tips:設定物件關聯需要以下幾個要點:
源物件關鍵字關聯的物件 關聯策略
解釋一下:這裡我將@"content_yeah"這個物件與self使用OBJC_ASSOCIATION_RETAIN_NONATOMIC策略關聯到一起,意思就是在self的生命週期之內關聯的物件都不會被釋放,通過這個方法,可以實現動態向類裡面新增屬性
另外還有一些關聯的方法,如

  • 斷開關聯: 設定關聯物件為nil即可
    objc_setAssociatedObject(self, &associatedKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  • 斷開這個物件的所有關聯關係


JSON轉Model工具的主要介紹


1. 為什麼會寫這樣一個工具

很多時候我們並不是缺少實力,而且是缺少一種彼可取而代之的勇氣,為什麼會有MJExtensionYYModel的產生,檢視原始碼的過程中我有種想死的感覺,但是知道實現的原理後,為什麼不能自己去實現一個呢?這個工具的原始碼非常簡單,我寫這個工具的目的只是為了告訴朋友們,真的不復雜,不要因為看著複雜就放棄了自己動手的衝動

2. 工具的整體步驟簡介

著重介紹一下我的思考過程

  • 1 核心方法?
    利用Runtime可以遍歷出物件的所有屬性,然後利用遞迴的思想逐層解析JSON
  • 2 怎麼去做?
    基本所有的Model繼承NSObject,我們可以寫一個NSObjectCategory,然後在其中寫一些解析方法,我們需要一個對照JSON字串的解析路徑字典,比如說JSON的屬性名稱為dog,我們的物件屬性名稱想定義為xiaogou,這就需要手寫一個字典將解析中遇到的dog都給對映為xiaogou
  • 3 開始動手吧

3. 主要程式碼介紹:


* 1 NSObject+CMModel 介紹

下面著重解釋一下.m檔案中的內容

取得物件的所有屬性及其對應的型別
Tips: 這裡自己寫了一個類,將物件的屬性及其名稱封裝到一個型別為CMProperty的陣列

  • 1 CMProperty類簡介

  • 2 獲取物件屬性及其型別,並且將其封裝為型別為CMProperty的陣列

開始解析

* 2 CMObject 介紹

這個類為實際進行解析工具的類,或者可以稱之為工具,這裡我們需要特殊對待NSArrayNSDictionaryint、float等基本型別

Tips: 下面程式碼可能看著會不舒服,我說一下整體的思路

* 1 NSObject+CMModel中將封裝的屬性陣列傳遞過來,我們一個接一個的對屬性進行遍歷構造

2 遍歷詳解:舉例,碰到NSArray的屬性時,我們去看要解析的類中實現的- (NSDictionary )dict_CMModelWIthArrayClass這個方法,找到目的物件的型別OBJClass,然後將JSON字典拆分後利用- (instancetype)cm_initWithJSONString:(NSString *)jsonString這個方法建立一個OBJClass型別的物件,並且新增到陣列中,建立完後,使用KVC將陣列賦給源物件,具體程式碼看下面


4. 如何使用


舉例說明:
這裡有三個類
Animals(動物)

—實現方法:

Dog(狗)

—實現方法

Pig(豬)

—實現方法

呼叫方法

寫在後面的話

這個專案並不完善,比如說對於其中日期的格式化,非空的一些判斷等,其中也有一些bug,本文權當是拋磚引玉,利用Runtime可以做很多事情,比如你可以實現,一句話完成歸檔與解歸檔,不會再出現Model屬性過多時重寫initWithCoderencodeWithCoder的尷尬了,so,有時候我們更缺的是一種思考問題的方式,共勉!

PS:歡迎來我的簡書、Github、個人部落格交流?

文中的Demo下載地址

相關文章