乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      為什么唱吧iOS 6.0選擇了Mantle | iWangKe.me

       螢火與皓月 2016-01-27

      Github for Mac

      最近唱吧iOS的6.0版本已經(jīng)成功上線了。18人月的投入,2500個commit,幾十萬行的代碼修改。唱吧iOS已經(jīng)從內至外煥然一新,感謝一起并肩作戰(zhàn)的小伙伴們。

      6.0一個很重大的修改就是基于Mantle重建(新建)了Model層。這里不對Mantle作更多介紹,只分享一下使用Mantle的決策及執(zhí)行過程。

      我們遇到的問題

      唱吧是一款上線2年多的App,產(chǎn)品形態(tài)的演進和迭代非常快。因此不可避免的遺留了各種問題:

      • Model層不健全,沒有統(tǒng)一的結構,不同工程師做法差異很大;多數(shù)是啞類型,且沒有統(tǒng)一的序列化機制
      • 業(yè)務邏輯冗余、分散、不一致
      • 模塊劃分隨意,依賴關系混亂,維護困難
      • NSDictionary作為承載業(yè)務的數(shù)據(jù)類型在各處出現(xiàn)(sqlite, Model object, API, Notification, web, OpenURL etc.),參數(shù)和值的正確性完全沒有編譯器檢查,字符串很容易寫錯,風險延后至運行時,易產(chǎn)生低級bug
      • 基本沒有文檔和注釋(結合上一點,不掛debugger很難讀懂代碼)
      • 幾百個API,業(yè)務復雜,變動快,重構難;同一個API請求可能有重復和不一致
      • API的一些參數(shù)和返回值,同一個參數(shù)/返回值可能存在類型差異;由于API需要向前兼容,修改API有成本

      除此之外,還有其他工程上的約束:

      • 不能影響現(xiàn)有的API,所有的事情只限于iOS端的修改
      • 代碼即文檔,因為沒有精力維護文檔
      • 對不同Model的持久化方式作遷移
      • 避免寫大段枯燥的Model的序列化/反序列化代碼
      • 沒有時間造出足夠成熟、健壯可重用的組件及撰寫文檔

      上述的問題都是長期存在且需要解決的,否則嚴重影響開發(fā)效率及代碼質量。11年的時候我還在做社交游戲的時候,設計并實現(xiàn)了一套簡單的基于Objective-C Runtime的數(shù)值表Model結構及轉換工具(Model<=>csv)供數(shù)值策劃使用。但想寫出一套成熟的方案還是有一些距離,而且也沒有資源和時間作維護、測試和文檔。

      順著這個思路找到了JSONModelMantle,前者剛剛1.0,后者在Github for Mac中廣泛使用且社區(qū)更成熟(甚至Slack上有channel),所以成為了更好的選擇。

      事實也證明這個選擇是對的,6.0上線后,crash率比之前的版本有顯示的降低,并且Mantle相關的crash占總crash的比率不到3%,大可以直接用在大型的產(chǎn)品上。

      除了成熟穩(wěn)定,Mantle基本解決了我們遇到了的所有問題。下面具體介紹一些通用性Mantle使用經(jīng)驗,基本的使用方法請直接移步Mantle的README

      Property名稱轉換

      由于API使用的開發(fā)語言與iOS所使用的Objective-C是截然不同的,所以可能將一些保留關鍵字作為property的名稱(如id),或者不小心override掉基類的屬性(如description)。還有可能API中使用了一個很糟糕的名稱,或者使用了不符合Objective-C命名規(guī)范的名稱,這些我們都需要作轉換。

      只需要實現(xiàn)MTLJSONSerializing protocol并在+JSONKeyPathsByPropertyKey方法中定義好新舊名稱的映射關系即可,Mantle會在序列化及反序列化時對屬性名進行自動的轉換。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      + (NSDictionary *)JSONKeyPathsByPropertyKey {
      return @{
      @"identifier": @"id",
      @"displayDiscription": @"description",
      @"thisIsANewShit": @"newShit",
      @"creativeProduct": @"copyToChina",
      @"betterPropertyName": @"m_wired_propertyName"
      }
      }

      好了很多吧?沒錯,只需要定義一次名稱的映射關系就可以了,Mantle負責model與JSON之間的雙向轉換。不需要將這種邏輯寫得到處都是,并且還得維護它的一致性。

      Property的類型映射

      iOS中處理URL使用的是NSURL類型,但JSON只支持基本的字符串,Mantle可以自動幫你轉換成NSURL。

      1
      2
      3
      + (NSValueTransformer *)URLJSONTransformer {
      return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
      }

      NSValueTransformer負責在不同類型間進行雙向轉換,請讀者研究一下Mantle的實現(xiàn)方式。在此前提下,留給讀者一個問題(其實這是一個真實的故事,類似的故事還有很多,詳見iOS應用開發(fā)之十大坑隊友):

      假設我們有一個entity,名字且叫KTVConcreteEntity吧,它有一個屬性名字叫entityID,類型是NSInteger。問題來了,entityID可能在另外一個API的response中是字符串類型,在不直接修改Mantle的源碼的前提下怎么搞?歡迎在下方留言討論。

      空標量異常

      有的時候API的response會有空值,比如copyToChina可能不是每次都有的,JSON是這樣兒的:

      1
      2
      3
      {
      "copyToChina": null
      }

      Mantle在這種情況會將newShit轉換為nil,但如果是標量如NSInteger怎么辦?KVC會直接raise NSInvalidArgumentException。

      Mantle是基于KVC給property賦值的,KVC提供了- (void)setNilValueForKey:(NSString *)key方法,讓我們?yōu)閚il指定一個合理的替代值,我們來看一下此方法的解釋:

      Invoked by setValue:forKey: when it’s given a nil value for a scalar value (such as an int or float).
      Subclasses can override this method to handle the request in some other way, such as by substituting 0 or a sentinel value for nil and invoking setValue:forKey: again or setting the variable directly. The default implementation raises an NSInvalidArgumentException.

      對于標量來講,多數(shù)情況下合理的值即為0,我們來看下代碼:

      1
      2
      3
      4
      5
      6
      7
      8
      @interface MTLModel (KTVNullableScalar)
      @end
      @implementation MTLModel (KTVNullableScalar)
      - (void)setNilValueForKey:(NSString *)key {
      [self setValue:@0 forKey:key]; // For NSInteger/CGFloat/BOOL
      }
      @end

      問題完美解決,再也不需要到處寫無聊的if/else了。

      其它重要特性

      Mantle為我們帶來的方便不勝枚舉:

      • 實現(xiàn)了NSCopying protocol,子類可以直接copy是多么爽的事情
      • 實現(xiàn)了NSCoding protocol,跟NSUserDefaults說拜拜
      • 提供了-isEqual:-hash的默認實現(xiàn),model作NSDictionary的key方便了許多
      • 簡單且把一件事情做好,不摻雜網(wǎng)絡相關的操作

      如此強大優(yōu)雅的設計,讓我不得不向Github的工程師們致敬!

      寫在后面

      篇幅所限,只介紹了幾個典型的問題,歡迎大家討論。但如果你的App的代碼規(guī)模只有幾萬行,或者API只有十幾個,或者沒有遇到我們這些遺留問題,我建議還是不要引入了,殺雞用指甲刀就夠了,殺不動多磨磨找準要害。Anyway,Mantle的實現(xiàn)和思路是值得每位iOS工程師學習和借鑒的。

      附小廣告一則:唱吧iOS團隊誠招iOS工程師,推薦成功即獎勵6000元現(xiàn)金或iPhone 6一部,詳見這篇blog。

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多