《iOS App 開發的那些事兒》系列文章從更巨集觀的角度出發,不僅僅侷限於具體某個功能、介面的實現,而是結合網易雲信 iOS 端研發負責人多年的經驗,從如何優化現有程式碼的角度出發,深度分析如何創造出 iOS App 開發中比較合適的規範和框架。
推薦閱讀
《iOS App 開發的那些事兒 1:如何建立合適的規範》
一個合適的框架不是銀彈,在我看來框架要解決的問題從來不是:有了框架之後,工程就能無比正確地進行下去。好的框架能夠做到的事僅僅只是:降低通用問題的複雜度和減少發生錯誤的可能性。個人認為一個良好 iOS App 框架應該是有如下特點:
定義清晰的層次結構
- 橫向上,各模組互相獨立,僅通過有限的幾個介面進行通訊。最理想的狀態是除核心模組外,其他模組都是可拔插。縱向上,各層次間依賴關係清晰,基本不出現逆向依賴的情況。
- 橫向模組一般依賴於業務需求,常被定義成各種 Service 或 Manager。一種好的做法是有個統一的 Service 管理器負責相應 Serivce 的載入,解除安裝,監聽和分發 App 級別的通知給相應 Service,如前後臺切換,收到記憶體警告等。這樣做一方面容易實現上面說的模組的可插拔化,另一方面也保證了公用特性處理的一致性。在這方面微信就做得不錯,基本所有的模組都是從MMService繼承而來,由 MMServiceCenter 進行管理。當然從 dump 出來的標頭檔案也可以發現一些管理上的紊亂,比如一些 ViewController 都是繼承自 MMService。
- 縱向的層次劃分基本各個 App 不會有太大區別,一般可以分為三個層次:
展現層(Presentation layer):負責管理 UI 和 UIViewController。
邏輯層(Business/Service Layer):負責邏輯資料的定義和轉發,起到承上啟下的作用。
資料訪問層(Data Access Layer):負責具體 API 構造,網路請求,資料持久化等。
各層根據業務邏輯的複雜性內部又會使用單層或者多層結構。以資料訪問層為例,一般又可以細分為網路層,持久化層。而一般而言,展現層(UIView 和 UIViewController)都是直接使用邏輯層提供的Model進行展現,但是某些場景下往往需要不同的Model有相同的介面展示(如我們的 App 易信中,會話介面,收藏介面,問一問功能都需要進行圖片的展現,但這三個模組下的 Model 定義並不一致),這就需要增加額外的 ViewModel 層用於粘合展現層和邏輯 Model。
遵守 SOLID 原則和慎用各種設計模式
這是個老生常談的話題了,並不是 iOS 開發獨有,展開講可以講上幾天幾夜,不贅述。
定義自己的UI基類:UIView,UIViewController,UITableviewCell
這一點的好處不言而喻,所有的子 View,Controller,Cell 都能夠很方便的繼承基類的共有的行為,樣式。但也會引進很大的管理風險:組內成員總會經不起誘惑往基類塞各種並不普適的特性,引起基類權責的無限膨脹。大基類不僅增加組內成員對程式碼的理解難度,同時也增加出現問題時的排查難度。從這方面講,微信的 UIViewController 基類設計就極端失敗:MMUIViewController 這個類光標頭檔案就有上百行。
提供方便好用的工具類
一些好用的工具類往往會成為框架重要的有機組成部分,方便快捷地解決區域性問題,同時又不引入過多的複雜度。NSTimer 的 retain cycle 是個很容易掉去的坑,那麼提供一個基於 Block 或者 weak delegate 的 NSTimer 的封裝就是不錯的選擇。使用 KVO 容易發生 add 和 remove 的不配對呼叫,那麼就引入THObserversAndBinders 或者 FB 的 KVOContorller。某些核心模組需要被多個模組依賴時,引入類似 XMPP 的GCDMulticastDelegate 就能夠方便地進行解耦。
好的範例
在前幾年使用 C++ 的那段暗無天日的日子裡,我常想的一個問題是:如何在 API 層面去限制和規避一些錯誤。比如往執行緒池裡面扔的 task 必須是堆上分配的物件,那麼如何去強制傳入的指標指向的是堆地址而不是棧地址呢?這種傻問題大部分情況下是無解的,有時候有解卻是個異常彆扭的解。而現在我更相信破窗理論所提供的可能性:做好示範,接下來的一切都會水到渠成。
大家可以戳《iOS App 開發的那些事兒 1:如何建立合適的規範》回顧該系列第一篇文章,也歡迎大家積極發表自己的看法,與我們共同討論。
隨著即時通訊以及音訊處理和壓縮技術的不斷髮展,效果更好、適用範圍更廣、效能更高的演算法和新的技術必將不斷湧現,如果你有好的技術或者分享,歡迎關注網易雲信官方部落格和 GitHub:
關注更多技術乾貨內容:網易雲信部落格
歡迎關注網易雲信 GitHub
歡迎關注網易雲信官網