iOS的Mantle實戰

來源:互聯網
上載者:User

標籤:style   blog   http   io   color   os   ar   使用   for   

公司項目之前的model層代碼是我使用JSON工具直接產生Objective-C代碼的,當時還是覺得相當省事的,畢竟我經曆過無model層的NSDictionary“黑暗”時期。但是隨著項目的推進,問題開始慢慢顯現出來。

於是,在一個多月前,我在Objc.io上看到提及了Mantle,花了一點時間看了一下,決定先在分支上全套改用Mantle。使用了一段時間,效能沒造成什麼瓶頸,穩定性還是可以接受的。後來也基於Mantle、MK和RAC,把網路的請求整合在一起,在新項目上全面使用。一開始時也是沒什麼問題的,但後來我也逐漸發現了Mantle雖好,但不至於能解決一切問題。最近看到了《為什麼唱吧iOS 6.0選擇了Mantle》文章,我決定寫部落格記下一些model層的坑。

 

簡要分析

先來簡要分析一下各種構建model層方法的優點和缺點:

一、工具產生model

優點:

1、簡單易用,新手也可以10秒上手

2、有一定的容錯代碼

3、代碼產生相對工整和規範,部分工具還可以選擇是否使用ARC

4、產生簡單model耗時少

缺點:

1、工具產生的類名或者屬性名稱不太符合要求,往往需要自行修改,但是修改起來相當麻煩,卻需要相當專註以防有什麼地方忘記修改。

2、產生的程式碼相當冗長。

3、對適應欄位變化比較麻煩,一旦屬性需要修改欄位時,要麼人工修改,要麼重建,但是極有可能需要重複缺點1的步驟。

4、model之間一些繼承關係還是需要自行修改繼承來實現。

 

二、基於運行時產生的model(Mantle這類)

優點:

1、減少大量模版代碼

2、修改欄位對應時相當簡便

3、擴充時相對方便

4、可以實現更多複雜的映射關係和數值轉換

5、調試時的異常可以較好地發現問題

6、實現了NSCopying和NSCoding協議,可以輕鬆序列化

缺點:

1、基於運行時屬性對應,對效能有一定影響

2、有部分容錯處理需要自行解決,否則很可能崩潰(下文詳解)

3、架構代碼不少

 

三、NSDictionary型model

優點:

1、無需任何基礎,直接可用

2、容錯性相對較高

3、無視任何資料結構,均能適應

缺點:

1、維護成本昂貴

2、編譯器無法檢查拼字,需要定義大量key的常量,否則極其容易寫錯

3、調試相對麻煩

 

其實,NSDictionary型model還是有一定用途的,畢竟有些情況下,不需要浪費精力去構建一個很短小或者很快就會被釋放的model。但大多數情況下,還是需要去構建一個合理的model,來保證項目的健壯性和開發效率。以前,我老大和我說,iOS應用MVC三層,M這一層其實服務端已經幫你完成了大部分,來到用戶端再自己處理model,既消耗效能又降低了開發效率。當時,我覺得還是比較正確的,但隨著MVC的C變得臃腫不堪,M變得越來越輕量的時候。很多東西都耦合在controller,model這層能做好的話,就能一定程度上減輕了controller的複雜度。加上工作了以後發現,一個只有NSDictionary,無真正model的商業應用,真的非常不利於維護。

基於上述的種種理由,我還是決定了正式全面使用Mantle。但Mantle不是萬能的,我還是遇到了幾個問題。

 

null值

如果你的屬性是基本數實值型別的話,JSON返回一個null值,那麼在Mantle產生model的時候,果斷崩潰了。這個問題和解決方案跟《為什麼唱吧iOS 6.0選擇了Mantle》中的一樣,model中實現一下setNilValueForKey:方法即可。建議使用基類繼承,那麼寫一次這個方法就所有model都解決了這個問題。

 

索引值的合理映射

1 {2     "code": 13     "result":{4         "access_token":"m_xxxxxxx",5         "user_id":11116     }7 }

例如上述JSON,假設整個JSON是一個model,那麼如果直接按照JSON的格式來映射,就要建立一個“result”額外的model類。但或許不需要這麼繁複,其實可以這麼寫

1 + (NSDictionary *)JSONKeyPathsByPropertyKey2 {3     return @{@"accessToken": @"result.access_token",4                   @"userId": @"result.user_id"};5 }

這樣做就可以很方便地映射到對應的屬性上,同時也不需要額外建立一個model類。這裡為什麼沒寫“code”的映射呢,因為如果屬性名稱和JSON的鍵名一致時,是可以省略不寫映射的,具體大家可以看看Mantle的源碼。

 

值的類型問題

這個問題是最棘手的,不能說後台坑隊友,但是JSON的數實值型別和文檔不符乃家常便飯。作為和使用者最近的前線,我只能想盡辦法去收尾,不能完全放任不管吧。常規的方法不外乎以下幾種:

1、轉換model前先進行預先處理JSON資料,把類型不符的值轉換或者刪除掉

2、為這些容易崩潰的值,都寫上NSValueTransformer的轉換

 

這些的確都能解決問題,但是效率就下降了很多,你得關注各種各樣的可能出現的情況。相信我,要是你這麼做,你連睡覺都睡不好。

我列舉一下幾種類型不符會導致的異常:

1、屬性是BOOL類型,傳回值是string類型。

2、屬性是NSString類型,傳回值是number類型,Mantle只會轉換出NSNumber類型。你調用length等NSString的專用方法時,你懂的。

3、使用了類似上面"result.access_token"的映射,但傳回值不是object類型(例如array類型)。

4、屬性是NSArray,使用了轉換,傳回值是object。

 

放心,實際情況中,絕對不會只有上述4種可能的。不過幸運的是,Mantle幫大家處理了1、3、4這些情況(如果object和array都是使用了轉換方法的話,在轉換的時候會處理這些異常的),只會在偵錯模式下拋出異常,Release的時候是不會崩潰的。如果大家不想在調試的時候被這些異常打斷的話,可以注釋掉MTLValidateAndSetValue這個方法中的對應代碼。

接下來大家可能覺得太匪夷所思了,為什麼一個小小的用戶端還得因為用個Mantle就要去規避這麼多陷阱。我就是遇到這麼多陷阱,想到瞭解決方法,自己也是成長了。針對JSON的類型,我有了以下的考慮:

JSON其實就是只有4種類型,string、number(int 、bool…)、object、array。在Objective-C對應也就是,NSString、NSNumber、NSDictionary、NSArray,因此要規避類型問題也是從這幾個類著手。這裡要說一下為什麼屬性有int、bool等,我只歸了一類NSNumber。因為實質上,Mantle只是轉換了NSNumber類型的對象出來,在setValue的時候,是由系統根據類型調用了對應的NSNumber方法。由於number和string的類型錯誤是最常見,同時也是最隱形(調用類似intValue的方法看不出端倪),為此我寫了一個AvoidMTLModelCrash的category,github上的地址,使用了這個category以後,關於NSString和NSNumber類型問題的崩潰基本都可以解決。如果是NSArray或者NSDictionary設定到NSString的屬性也是無法檢測的,但是面對如此嚴重的類型問題,我建議還是和小夥伴一起坐下來,好好談談“人生”吧。

 

靈活的轉換

例如某些介面返回的資料是數組,但很多時候只需要用到這個數組的第一個元素。我們可以直接將數組裡面的一個元素影射出來。

1 + (NSValueTransformer *)pointListJSONTransformer2 {3     return [MTLValueTransformer transformerWithBlock:^id(NSArray *array) {4         return [array firstObject];5     }];6 }

除了屬性對應和每個屬性固定的類型轉換,MTLJSONSerializing的協議還有classForParsingJSONDictionary這麼一個方法可以改變解釋後的類。例如B、C均繼承A,用Mantle產生A類對象。A類可以通過這個方法,選擇不同的子類產生對象。但是對外可見的介面也是A類的介面,這樣就類似NSArray一樣(NSArray其實也是有很多子類的)。

 

小小的總結

model的架構對項目影響深遠,如果為了不在以後的項目留下坑,那model這一層還是要多加思考,免得造成了維護不能的境地。

iOS的Mantle實戰

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.