iOS應用千萬級架構:MVVM框架

jiangys發表於2020-07-06

業務模組內的MVC和MVVM架構

目前,唯品會中MVC和MVVM架構並存,後期會偏重於MVVM架構的使用。

MVC架構

Model:程式中要操縱的實際物件的抽象,為Controller提供經過抽象的業務資料,供Controller排程

View:檢視,負責介面的元素的展示

Controller:控制器,管理View的宣告週期及子view的生成和組裝,負責Model和View之間的通訊。

MVC框架的優勢:
1. 應用廣泛,幾乎所有前端語言都有類似MVC的設計痕跡
2. 設計思想非常簡潔,學習成本很低,新人上手非常容易。

MVC框架的問題:
MVC並沒有對資料請求和處理邏輯程式碼應該放在哪一層做出明確地劃分,因此一旦頁面邏輯或互動稍微複雜,Controller就會變得很臃腫,程式碼也就越來越難維護。

MVVM架構

MVVM框架是在MVC的基礎上演化而來,MVVM想要解決的問題是儘可能地減少Controller的任務。

Model:程式中要操縱的實際物件的抽象
View(ViewController):MVVM中的View不再是UIView的子類,而變成了UIViewController的子類。這裡的View實際上就是MVC中剝離了處理呈現View邏輯部分的Controller,因此它仍然有各種UIView的屬性,仍然有ViewController的宣告週期的各種方法,但是這裡的Controller不再負責資料的請求以及處理邏輯,因此不再臃腫。
ViewModel:MVVM中,ViewModel代替了MVC中的Controller成為了協調者的角色,ViewModel被View(ViewController)持有,同時持有者Model。資料請求以及處理邏輯都放在ViewModel中,View(ViewController)就瘦了下來。

MVVM框架的優勢:
1. View(ViewController)通過對ViewModel中的資料進行繫結來更新介面,不用通過邏輯或者條件判斷來更新view,大大降低了複雜互動時出bug的機率。
2. View(ViewController)中程式碼簡潔,後期的維護和優化比較容易。

MVVM框架的問題:
學習成本比MVC高,如果對MVVM的職責劃分理解不透徹,很容易導致ViewModel的存在形同虛設, 反而增加了維護的成本。

我們為什麼要用MVVM?

訂單售後這個頁面內容非常多,而且裡面的內容會變,還可以收縮展開,還會出現由介面請求成功或失敗來控制某一部分的顯示還是隱藏。當你使用普通的MVC架構的時候,你會發現,在controller裡的程式碼量非常驚人的,View的計算也非常複雜,當有一塊內容要在中間展示的時候,下面的所有的View的Y值都得重新計算。顯然,維護成本是非常高的,改動一個小點還可能會導致蝴蝶效應,測試也要回歸當前頁面所有的用例。

那有沒有好的辦法來解決這些問題呢?我只想在自己的小塊里加功能,當小塊的內容高度變化了,整個頁面的佈局高度跟著自己變化呢。答案是有的,那就是使用MVVM模式。

看下圖的UML類圖,分析一下,如下:

下面就CollectionView做說明,每一個內容都是一個小塊Cell,都有自己的cellViewmodel,整個控制器有一個大的viewmodel,包裝所有的cellViewmodel,就這樣構建一個頁面。

1、itemCell 是小塊Cell,裡面主要是初始化View,更新View的資料,需要返回cell的寬高

2、cellViewModel,是itemCell的ViewModel,給itemCell 提供資料,itemCell的點選事件也是回撥到cellViewModel中。

3、Cell1ViewModel 和 item1Cell 組成一個小塊Cell1

4、Cell2ViewModel 和 item2Cell 組成另一個小塊Cell2

5、ViewModel 網路請求拿到資料之後,組裝上面的小塊Cell1ViewModel、小塊Cell2ViewModel,通過方法【 - (Class)cellClass 】就可以拿到當前的itemCell

6、ViewModel中,還通過block的方式,對Controller回撥繫結了事件,比如cell的點選事件、載入資料成功事件、按鈕點選事件等

例子

Demo有兩種處理方式,一是通過繼承基類,重寫基類的方法來實現;二是通過協議,cell使用cellprotocol協議,cellModel使用cellModelProtocol協議。

使用方法

直接繼承MVVMBase使用

  1. 新建一個控制器VSDemoCollectionViewController,繼承於VSMVVMCollectionViewController
  2. 新建一個該控制器的ViewModel(VSDemoCollectionViewModel),繼承於VSMVVMCollectionViewModel,負責管理所有的CellViewModel
  3. 新建一個CellModel(VSDemoCollectionItemCellModel),繼承於VSMVVMCollectionViewCellModel,負責管理元素Cell,在方法cellClass中,返回關聯的Cell(VSDemoCollectionItemCell)
  4. 新建一個Cell(VSDemoCollectionItemCell),繼承於VSMVVMCollectionViewCell,需要重寫VSMVVMCollectionViewCell中的方法,返回該cell的高度。
  5. 頁面很複雜,需要重新步驟3和4,不斷的拆分這個複雜的Cell.
  6. 最後,所有的cellModel都交由第2步的控制器的ViewModel整合載入。

原始碼

程式碼Demo已經上傳到github: https://github.com/jiangys/VSMVVM 

 

相關文章