iOS 手動打造JSON Model轉換庫

發表於2016-04-10
前一段時間學習了Runtime,對類和物件的結構,和一些訊息轉發有一些自己的理解,現在希望簡單的應用下,就決定自己寫一個簡單的JSON與Model的相互轉化,現在總結下。

建議檢視

觀察下面這個JSON資料和Model資料

開始的時候仔細想了一下,如何能夠動態的去新增屬性值,並且根據對應的屬性進行賦值,還要保證型別正確,這是我最開始考慮的問題。但是最核心問題就是動態實現

我們一步一步來解決問題,首先我們先獲取Model屬性,取得Model的一些資訊

獲取Model屬性

runtime提供了class_copyPropertyList來獲取屬性列表,OK,我們可以來看一下用它獲取的資料是什麼樣的?檢視runtime原始碼

 

PropertyInfo也就是屬性資訊,我們將Model的所有屬性存放到NSMutableDictionary中,key就是屬性名,Value就是PropertyInfo。

接下來開始獲取Model的屬性資訊PropertyInfo

我們可以通過property_getName來獲取屬性名,檢視原始碼

接下來就是獲取屬性的型別和一些其他的資訊。獲取屬性的資訊其實和上面的原理差不多,我們使用property_copyAttributeList,檢視下它的原始碼

看到這裡,不往下繼續分析原始碼了,其實可以看到,attributes就是我們想要的資訊,其實每個property也是有自己對應的attributes。

這個attributes是什麼樣呢?翻看原始碼,找到了答案

加一下斷點,看看

可以看到,name是T,Value是NSNumber,我們來獲取下NSNumber這個屬性型別。

基本上我們想要的資訊基本上都已經獲取到了,現在接下來就是做動態設定。

中間做個插曲簡單的說下Objc是動態語言,[receiver message]的執行過程當中,[receiver message]是會被動態編譯的,Objc是動態語言,因此它會想盡辦法將編譯連線推遲到執行時來做。runtime這個時實執行系統就是來執行編譯後的程式碼。想詳細瞭解,歡迎閱讀Runtime學習筆記

在這個訊息傳送過程中,objc_msgSend充當著很重要的角色,所以我們可以主動觸發objc_msgSend,來模擬getter,setter方法獲取屬性值,或者建立。

我們通過SEL來定義選擇器,選擇器是什麼?就是方法名的唯一識別符號

根據剛才的想法,編寫的程式碼最後是這個樣子

基本的準備工作,和一些問題都解決了,接下來可以寫功能了。

JSON轉Model

根據剛才說的,我們可以主動觸發objc_msgSend,來模擬setter方法建立屬性值。設計出以下方法

我們將Model的所有屬性存放到NSMutableDictionary中,key就是屬性名,Value就是PropertyInfo。

現在就可以動態設定了

完成動態設定

Model轉JSON

原理跟JSON轉Model

我們可以主動觸發objc_msgSend,來模擬getter方法來獲取屬性值。

建立NSDictionary

 

完成獲取

測試

結果:

總結

簡單的JSON Model轉換庫,關鍵點就是在於對runtime的理解。就當自己的一個小練習,後續會繼續維護,讓它對更多型別進行支援。程式碼結構上可能不是那麼好,後續會將整體的結構重新設計下,增加可讀性,也歡迎來提出建議。

相關文章