先說MVC吧
MVC,全稱是 Model View Controller
邮破,是模型 (model
)-視圖 (view
)-控制器 (controller
) 的縮寫。它表示的是一種常見的客戶端軟件開發(fā)框架;
MVC
這個概念最早出現(xiàn)在上個世紀(jì)八十年代(目測本文的讀者都還沒有出生,當(dāng)然筆者也沒有出生)被提出,之后被廣泛的應(yīng)用于各類軟件開發(fā)中.
iOS
開發(fā)也不例外,iOS
的系統(tǒng)架構(gòu)就是典型的MVC
,并且為我們實現(xiàn)了V
層和C
層的基礎(chǔ),然后開發(fā)者根據(jù)相應(yīng)的數(shù)據(jù)補充M
.這一切看起都很合理,而且開發(fā)者也一直都這么做著,并沒有什么不妥
嗯,是的,沒毛病...
但是事實真的如此么?
事實是,很多維護者會抱怨前人的代碼多爛多爛,真的沒法看,設(shè)計模式一塌糊涂等等;
這時候的MVC
可能會變成(Massive View Controller
),controller
里面塞滿了各類業(yè)務(wù)代碼,多大上千行,甚至更多,如果注釋寫的好一些,勉強能看,如果沒有注釋...
為什么會這樣?這里的原因太多了,比如有些開發(fā)者在做iOS
之前并沒有聽說過MVC
,有些即使知道MVC
,也根本無法明確MVC
到底干嘛的?面試官經(jīng)常會問到這個問題,而得到的答案也僅僅是解釋MVC
概念之類,很少有人會在解釋完概念之后再去仔細(xì)的闡述一下結(jié)構(gòu)設(shè)計,代碼規(guī)范之類...
下面我們仔細(xì)剖析一下,到底該如何MVC
?
真正的MVC
我們來看看 MVC
這種架構(gòu)的特點。其實設(shè)計模式很多時候是為了 Don't repeat yourself
原則來做的饲鄙,該原則要求能夠復(fù)用的代碼要盡量復(fù)用谬以,來保證重用强饮。在 MVC
這種設(shè)計模式中,我們發(fā)現(xiàn) View
和 Model
都是符合這種原則的为黎。
對于View
來說邮丰,你如果抽象得好,那么一個App
的動畫效果可以很方便地移植到別的App
上铭乾,而Github
上也有很多UI
控件剪廉,這些控件都是在View
層做了很好的封裝設(shè)計,使得它能夠方便地開源給大家復(fù)用炕檩。
對于Model
來說斗蒋,它其實是用來存儲業(yè)務(wù)的數(shù)據(jù)的,如果做得好笛质,它也可以方便地復(fù)用泉沾。比如我當(dāng)時在做有道云筆記 iPad
版的時候,我們就直接和iOS
版復(fù)用了所有的Model
層的代碼妇押。在創(chuàng)業(yè)做猿題庫客戶端時,iOS
和iPad
版的 Model
層代碼再次被復(fù)用上了跷究。當(dāng)然,因為和業(yè)務(wù)本身的數(shù)據(jù)意義相關(guān)敲霍,Model
層的復(fù)用大多數(shù)是在一個產(chǎn)品內(nèi)部俊马,不太可能像 View
層那樣開源給社區(qū)丁存。
說完 View
和 Model
了,那我們想想 Controller
柴我,Controller
有多少可以復(fù)用的解寝?我們寫完了一個 Controller
之后,可以很方便地復(fù)用它嗎屯换?結(jié)論是:非常難復(fù)用编丘。在某些場景下,我們可能可以用addSubViewController
之類的方式復(fù)用 Controller
彤悔,但它的復(fù)用場景還是非常非常少的嘉抓。
如果我們能夠意識到 Controller
里面的代碼不便于復(fù)用,我們就能知道什么代碼應(yīng)該寫在 Controller
里面了晕窑,那就是那些不能復(fù)用的代碼抑片。在我看來,Controller
里面就只應(yīng)該存放這些不能復(fù)用的代碼杨赤,這些代碼包括:
- 在初始化時敞斋,構(gòu)造相應(yīng)的 View 和 Model。
- 監(jiān)聽 Model 層的事件疾牲,將 Model 層的數(shù)據(jù)傳遞到 View 層植捎。
- 監(jiān)聽 View 層的事件,并且將 View 層的事件轉(zhuǎn)發(fā)到 Model 層阳柔。
MVC反面教材
直接上代碼吧:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
cell.textLabel?.text = "二狗子"
cell.imageView?.image = UIImage(named: "")
return cell
}
上面這段代碼,咋一看也沒啥,因為只有6行而已,但是這是因為上面的cell
數(shù)據(jù)加載很簡單,只有一個text
和image
,但實際開發(fā)中,我們的數(shù)據(jù)可不是這樣的,如果是新浪微博那種cell
我想,單單是cell
的數(shù)據(jù)加載都能寫個上百行;所以這種寫法是完全違反MVC
原則的,因為你在C
里面干了V
的事情, C
只應(yīng)該做數(shù)據(jù)傳遞;所以,嚴(yán)格遵循MVC
原則的寫法是,不管cell
的數(shù)據(jù)加載多么負(fù)責(zé),代碼都應(yīng)該是下面這樣的:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
cell.userModel = dataModel[indexPath.row]
return cell
}
如果你的tableview
是個標(biāo)準(zhǔn)的反面教材,請在評論區(qū)留下你的大名??
這里只是簡單的做了一些代碼結(jié)構(gòu)的調(diào)整,但是確實符合了MVC
原則,但是在controller
中往往不止這些東西,controller
最頭疼的問題,就是網(wǎng)絡(luò)請求問題,因為復(fù)雜的界面會涉及到很多數(shù)據(jù)請求,而這些請求也會伴隨著界面和數(shù)據(jù)的變化,這些邏輯寫上去,那么controller
的代碼量瞬間就上去了,幾個版本迭代過去,你懂的!所以,達到上千行只是時間問題?
何解?
在網(wǎng)上關(guān)于這個問題的答案有很多,比如分離網(wǎng)絡(luò)業(yè)務(wù)層,直接放到一個專門的業(yè)務(wù)模塊里面,MVVM
就是在這種情況下衍生出來的.
MVVM
MVVM
的歷史,這里就不贅述了,感興趣的同學(xué)直接百度,一大把,先看看一張基本上只要談到MVVM
都會放的一張圖:
上面這張圖,我想很多人肯定不止一次看到過
這個圖準(zhǔn)確的描述了什么是MVVM
:一個MVC
的增強版,讓view
和viewcontroller
直接結(jié)合在一起,使用ViewModel
進行鏈接,并將邏輯從controller
里面移出放到ViewModel
;MVVM
聽起來很復(fù)雜,但是他本質(zhì)還是MVC
,只不過在結(jié)構(gòu)上做了調(diào)整;這樣view
和model
徹底解耦了,那么這個時候他們之間的通信會變得有些奇怪了,因為他們中間跨越了一個層,所以在MVVM
的使用當(dāng)中,通常會利用雙向綁定技術(shù),使得Model
的變化能同步更新到View
上
那么這里就得提到一個框架:ReactiveCocoa
(swift
和Objective - C
都支持,但是在Swift
上更推薦使用RxSwift
);
ReactiveCocoa
是一個基于Cocoa
封裝的函數(shù)響應(yīng)式框架,使用它可以輕松的實現(xiàn)數(shù)據(jù)的綁定;所以,每每談到MVVM
的時候,總會提到它;但ReactiveCocoa
可以不想其他三方框架那般,看看Document
就可以開心的擼起來了,ReactiveCocoa
的Document
都能寫成一本厚厚的書了,而且最關(guān)鍵的是,它的編程思想,函數(shù)式,響應(yīng)式,數(shù)據(jù)流...
還有它那魔性的語法.
當(dāng)然了ReactiveCocoa
也提供了很多便捷:
- 函數(shù)式,提供了很多函數(shù)式操作(對于
Objective - C
來說,Swift
本身自帶) - 數(shù)據(jù)綁定,很多時候可以代替
KVO
,delegate
- 動態(tài)聲明
更多信息可以去官網(wǎng)閱讀相關(guān)文檔,本文這里不做太多探討;
要換MVVM?
既然MVVM
有那么多好處,為何不換?
在移動開發(fā)領(lǐng)域,MVVM
提出也不短了,可大部分項目還是使用MVC
,只有少部分項目會用;還有一部分項目會有專門的架構(gòu)師,為項目設(shè)計架構(gòu),他們會搞出一些大家都不懂的東西,然后在某個分享會上分享給大家;
但是!
我們要想清楚,你的項目真的需要MVVM
么?
不一定吧?
如果你的項目本來就不復(fù)雜,為何要換?MVC
就挺好的,別聽那些"分享"
筆者不是說那些分享不好,好,確實好,但,那是在他們的項目上用呀,他們都是就職于BAT
這樣的大廠的
一笑而過?
通過上面的閱讀,相信你已經(jīng)對MVC
和MVVM
有所了解,那么問題來了.
該用什么?
相信,很多iOS
開發(fā)者在找工作面試的時候都被問過MVVM
,基本上都快成了必問點了
我們不好說,哪個更好,哪個更適合.根據(jù)自己的情況選擇
MVVM
的學(xué)習(xí)路線相對要難很多,但是空閑的時候嘗試一下也是個不錯的實踐,其中收獲必定不小的
至少下次吹叛媸啵或面試的時候,你也多一些談資不是?
生命不息,折騰不止...
I'm not a real coder, but i love it so much!