iOS開發(fā)工程師份企,大部分時間要和界面打交道,由于蘋果的框架已經(jīng)為我們提供了最基礎(chǔ)的mvc的設(shè)計(jì)模式朵你,許多時候我們只是機(jī)械的添加著一個有一個的view controller, add 一個又一個的subView慎式,那么我們能不能從這些細(xì)節(jié)中脫身出來,到一個更高的層次來總結(jié)我們的iOS前端開發(fā)模式呢俊嗽,本文對常見的MVC設(shè)計(jì)模式及其變種進(jìn)行了總結(jié)。
一. 主動mvc
“主動—MVC”模式铃彰,也是通常意義下的MVC模式
何為主動绍豁?View不是等Controller通知它Model更新了然后才從Model取數(shù)據(jù)并更新顯示,而是自己監(jiān)視Model的更新(如果用觀察者模式)或主動詢問Model是否更新牙捉。前面那種等待Controller通知的方式是下面所介紹的“被動—MVC”的實(shí)現(xiàn)方式竹揍。】
二. 被動mvc(基本等同mvp)
1)Model 和 View 永遠(yuǎn)不能相互通信鹃共,只能通過 Controller 傳遞鬼佣。
2)Controller 可以直接與 Model 對話(讀寫調(diào)用 Model),Model 通過 Notification 和 KVO 機(jī)制與 Controller 間接通信霜浴。
3)Controller 可以直接與 View 對話晶衷,通過 outlet,直接操作 View,outlet 直接對應(yīng)到 View 中的控件晌纫,View 通過 action 向 Controller 報(bào)告事件的發(fā)生(如用戶 Touch 我了)税迷。Controller 是 View 的直接數(shù)據(jù)源(數(shù)據(jù)很可能是 Controller 從 Model 中取得并經(jīng)過加工了)。Controller 是 View 的代理(delegate)锹漱,以同步 View 與 Controller箭养。
三. 蘋果推薦的mvc
蘋果想要的的mvc和傳統(tǒng)mvc類似,是這樣:
但是哥牍,由于蘋果的貼心毕泌,每個vc都自帶一個view,所以蘋果的mvc變成這樣:
那么嗅辣,問題來了撼泛,這樣的模式導(dǎo)致的最重要問題:
model太輕,controller太重澡谭, 最后過于臃腫無法控制愿题,且無法進(jìn)行測試。 MVC 變成 Massive View Controller蛙奖。
四. Controller瘦身
根據(jù)唐巧的博客總結(jié)潘酗,C端瘦身可以抽象成下面幾個方法:
1. 將網(wǎng)絡(luò)請求抽象到單獨(dú)的類中
新手寫代碼,直接就在 Controller 里面用 AFNetworking 發(fā)一個請求雁仲,請求的完數(shù)據(jù)直接就傳遞給 View仔夺。入門一些的同學(xué),知道把這些請求代碼移到另外一個靜態(tài)類里面伯顶。但是我覺得還不夠囚灼,所以我建議將每一個網(wǎng)絡(luò)請求直接封裝成類骆膝。
把每一個網(wǎng)絡(luò)請求封裝成對象其實(shí)是使用了設(shè)計(jì)模式中的 Command 模式祭衩,它有以下好處:
- 將網(wǎng)絡(luò)請求與具體的第三方庫依賴隔離,方便以后更換底層的網(wǎng)絡(luò)庫阅签。
- 方便在基類中處理公共邏輯掐暮,例如猿題庫的數(shù)據(jù)版本號信息就統(tǒng)一在基類中處理。
- 方便在基類中處理緩存邏輯政钟,以及其它一些公共邏輯路克。
- 方便做對象的持久化。
2.將界面的拼裝抽象到專門的類中
新手寫代碼养交,喜歡在 Controller 中把一個個 UILabel 精算,UIButton,UITextField 往 self.view 上用 addSubView 方法放碎连。我建議大家可以用兩種辦法把這些代碼從 Controller 中剝離灰羽。
方法一:構(gòu)造專門的 UIView 的子類,來負(fù)責(zé)這些控件的拼裝。這是最徹底和優(yōu)雅的方式廉嚼,不過稍微麻煩一些的是玫镐,你需要把這些控件的事件回調(diào)先接管,再都一一暴露回 Controller怠噪。
方法二:用一個靜態(tài)的 Util 類恐似,幫助你做 UIView 的拼裝工作。這種方式稍微做得不太徹底傍念,但是比較簡單矫夷。
對于一些能復(fù)用的 UI 控件,我建議用方法一憋槐。如果項(xiàng)目工程比較復(fù)雜口四,我也建議用方法一。如果項(xiàng)目太緊秦陋,另外相關(guān)項(xiàng)目的代碼量也不多蔓彩,可以嘗試方法二。
3.構(gòu)造 ViewModel
這其實(shí)就是MVVM驳概。具體做法就是將 ViewController 給 View 傳遞數(shù)據(jù)這個過程赤嚼,抽象成構(gòu)造 ViewModel 的過程。
這樣抽象之后顺又,View 只接受 ViewModel更卒,而 Controller 只需要傳遞 ViewModel 這么一行代碼。而另外構(gòu)造 ViewModel 的過程稚照,我們就可以移動到另外的類中了蹂空。
4.專門構(gòu)造存儲類
剛剛說到 ViewModel 的構(gòu)造可以抽獎到一個 Service 層。與此相應(yīng)的果录,數(shù)據(jù)的存儲也應(yīng)該由專門的對象來做上枕。
數(shù)據(jù)存取放在專門的類中,就可以針對存取做額外的事情了弱恒。比如:
- 對一些熱點(diǎn)數(shù)據(jù)增加緩存
- 處理數(shù)據(jù)遷移相關(guān)的邏輯
- 如果要做得更細(xì)辨萍,可以把存儲引擎再抽象出一層。這樣你就可以方便地切換存儲的底層返弹,例如從 sqlite 切換到 key-value 的存儲引擎等锈玉。
五. MVVM
MVVM其實(shí)是MVVMC, 其實(shí)就是構(gòu)造了一個充血數(shù)據(jù)模型,并將充血的部分從Controller中劃到了ViewModel中义起,其模型如下:
View <-> C <-> ViewModel <->Model
比如一個最簡單的Name類拉背,從服務(wù)端拿到兩個屬性firstName與lastName,但是界面上需要展示的是fullName默终,這個時候可以構(gòu)造一個VM類椅棺,可以通過Name類的firstName yu lastName來組裝fullName抡诞。 當(dāng)然這是最簡單的一個例子,但基本就是類似的意思土陪。
MVVM 在使用當(dāng)中昼汗,通常還會利用雙向綁定技術(shù),使得 Model 變化時鬼雀,ViewModel 會自動更新顷窒,而 ViewModel 變化時,View 也會自動變化源哩。所以鞋吉,MVVM 模式有些時候又被稱作:model-view-binder 模式。
具體在 iOS 中励烦,可以使用 KVO 或 Notification 技術(shù)達(dá)到這種效果谓着。或者使用ReactiveCocoa坛掠。