打造強大的BaseModel(2):讓Model實現自動對映,將字典轉化成Model

ButterFly發表於2016-04-25

第一篇:《打造強大的BaseModel(1):讓Model自我描述

這篇文章將講述Model一項更高階也最常用的功能,讓Model實現自動對映–將字典轉化成Model(所有程式碼全由Swift實現)

將JSON轉化為Model的意義

在iOS開發中,基於Model的資料流起到了至關重要的作用。從網路獲取的資料需要進一步處理轉到成View可用的Model,再通過ViewController傳送給View展示出來,從View中反饋的資料也可以轉為為Model,再將Model轉化成JSON傳送給伺服器。通常開發過程中需要最頻繁處理的還是將JOSN轉化成對應的Model,目前市面上許多非常好用的JSON-Model庫,比如MJ大神的MJExtension,還有Matle及JSONModel。

目前我還從未在專案裡用到這些庫,有興趣的讀者可以自行去試試這些開源庫,也可以去看看它們的原始碼。這篇文章主要是討論如何用簡單的程式碼寫一個基類Model,讓子類可以自動實現從字典獲取資料再轉化為自身。功能並不算強大,但是還是比較實用的。

將字典轉化為Model這個過程中,最簡單便捷的情況就是字典的Key與Model的屬性名是一一對應的,這樣只要使用簡單的KVC即可完成JOSN-Model轉換。但是實際開發過程中很少出現這情況,也許你的命名風格和伺服器開發的同事的命名風格不一樣,也許同一個屬性名在不同的介面有不一樣的名字,總之很難達到這種理想的情況。我們最後還是要乖乖按伺服器的同事給的Key名來轉換。

先前我都是使用簡單的Dict[Key]的取值方式來實現JOSN-Model轉換,這種情況在Objc還是比較好用的,寫起來很方便,但是在Swift裡就完全行不通了,各種強制轉換寫起來很囉嗦很不爽。SwiftyJSON就是為了解決這種問題誕生的。用了SwiftyJSON看起來確實好了不少,但是還是要寫很多重複的程式碼來轉換,降低了開發效率。

使用KVC來實現字典-Model轉換

所以最好還是讓Model可以自動實現字典-Model對映。既然有這麼強大的KVC可以用,那為什麼不用呢?按照這個思路,我用Swift寫下了以下程式碼,先定義一個協議,裡面有一個靜態方法,目的是將一個字典轉化成一個Self物件

需要在GrandModel裡處理一些東西

在extension裡面實現協議

程式碼層次比較深,看起來有點亂,但總體邏輯卻很簡單。selfMapDescription是一個Class靜態屬性,它描述了字典的Key是怎麼和Model的屬性名是怎麼對映的。子類需要重寫這個屬性。

這是一個構造器,並且標記為required,說明是必需的。作用是保證該類是可以初始化的,只有這樣extension裡的self.init()語句才不會報錯。因為如果子類也不提供構造器的話,那麼該類不能正常用構造器例項化,也就是不能用init()方法了。

這個就比較好解釋了,在靜態方法裡面,self是一個Type型別,表示執行時的型別。它可以呼叫init()直接例項化一個執行時繼承於GrandModel的類。接下來的程式碼就比較簡單了,只要簡單將字典裡的Value用KVC一個一個給Model賦值就行了。賦值完成後再返回該物件

下面我們來看子類如何繼承該類,並且怎麼使用些功能

這裡有奇怪的地方,明明DemoClass有兩個Int型別的屬性,但是又說找不到?其實在這裡參考第一篇文章就很容易明白,這兩個屬性是Int?的型別的,而Objc裡面是沒有於之對應的型別的,可以在這個屬性前面加上@objc試試

打造強大的BaseModel(2):讓Model實現自動對映,將字典轉化成Model

可以看見XCode報錯了。Int?不能表現為Objc型別,所以在Objc執行時裡面是找不到與之對應的型別,自然不能加上@Objc標記了。
那麼怎麼辦?其實很簡單,給它一個初始值就行了,在執行時可以將其轉化成Objc的型別

現在列印出的結果是完全符合我們的預期了。KVC的強大之處在這裡表現得淋漓盡致,我們根本不需要理會這些基本資料型別,KVC可以幫我們搞定。

兩個問題和解決方案

但是目前還有兩個問題:一是如果介面有多種風格的屬性名,比如這個介面將UserName,另一個叫做sUserName,又或者叫userName等,多種不同的屬性名。至少我現在在做的專案至少有三種型別。其實這個非常簡單,直接把所有屬性的名字新增到selfMapDescription裡面就行

第二個問題,如果返回的資料裡巢狀了複雜型別,比如Array,Dictionary或者是其他物件等,KVC就不能幫你自動轉了

列印出的資料雖然看起來好像是正確的,但是其實格式是錯誤的。也就是說,KVC不能轉化複雜的或者自定義的物件。只能自己手動寫了。

這下列印出的東西就符合預期了,陣列物件也一樣,用個迴圈來轉化即可。

總結

上面的輕量型字典-Model轉換方案雖然在功能上不能和第三方的Json-Model庫相比,但對於大部分專案來說,還是夠用了。使用KVC帶來的效能上的損失我還是可以接受的,我討厭寫重複的程式碼。好了,以上就是第二篇的全部內容。

相關文章