一看就懂的极简MVVM
什么是MVVM
Model-View-ViewModel(MVVM)是基于MVC的變形的一種設計模式,它由Model、View、ViewModel三部分組成,三部分的職責如下:
- Model:負責表現應用的數據,它們通常是struct或者class。官方推薦使用struct定義Model。具體詳情可點擊這里。
- View:負責顯示在屏幕上的可視化元素,通常是UIView的子類。
- ViewModel:負責將Model中的數據轉化為View上顯示的數據。它們通常是class,這樣它們就可以通過引用指針來傳遞。
具體邏輯如下圖:
為什么要使用MVVM
當我們在項目初創時期,用MVC搭建項目是沒有問題的。但是隨著項目業務越來越多,越來越復雜的時候,我們會發現Controller里面的東西會非常的多,它通常會包含:Controller的生命周期函數、視圖的響應事件、遠程數據的獲取,數據的變形,各種邏輯的判斷等等。這樣會導致代碼閱讀性下降,bug率提升。這也是為什么大家調侃MVC為Massive-View-Controller的原因。
在這個背景下就誕生了MVVM設計模式來解決Massive Controller的問題,在使用MVVM的模式時,我們可以把數據轉換、數據邏輯判斷放在ViewModel里,以此來減輕Controller的負擔。
開始搭建MVVM
1、首先我們新建一個項目,創建一個Person.swift文件來表示用戶的數據:
//定義一個包含用戶名字、頭像和注冊時間的結構體當做用戶的Model struct Person {let name: Stringlet image: Stringlet registerTimeStamp: TimeInterval } 復制代碼2、接下來我們創建負責轉換Model的ViewModel-PersonViewModel.swift:
// name 和 image 只是簡單的通過兩個計算屬性來接受 // 將時間戳的注冊時間轉換為字符串的注冊時間 class PersonViewModel {let person: Personprivate var name: String {return person.name}private var image: String {return person.image}private var registerTimeStr: String {let date = Date(timeIntervalSince1970: person.registerTimeStamp)let dateFormatter = DateFormatter()dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"let strDate = dateFormatter.string(from: date)return strDate}init(_ person: Person) {self.person = person} } 復制代碼3、創建展示用戶信息的PersonView.swift:
class PersonView: UIView {let imageView = UIImageView()let nameLabel = UILabel()let registerTimeLabel = UILabel()override init(frame: CGRect) {super.init(frame: frame)backgroundColor = UIColor.brownimageView.frame = CGRect(x: (frame.width - 50)/2, y: 10, width: 50, height: 50)addSubview(imageView)nameLabel.frame = CGRect(x: 0, y: 80, width: frame.width, height: 20)nameLabel.textAlignment = .centeraddSubview(nameLabel)registerTimeLabel.frame = CGRect(x: 0, y: 110, width: frame.width, height: 16)registerTimeLabel.font = UIFont.systemFont(ofSize: 14)registerTimeLabel.textColor = UIColor.lightGrayregisterTimeLabel.textAlignment = .centeraddSubview(registerTimeLabel)}required init?(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")} } 復制代碼4、最后一步,在Controller中將它們連接起來:
class ViewController: UIViewController {let personView = PersonView(frame: CGRect(x: (UIScreen.main.bounds.size.width - 200)/2, y: (UIScreen.main.bounds.size.height - 300)/2, width: 200, height: 300))override func viewDidLoad() {super.viewDidLoad()view.backgroundColor = UIColor.whitesetupSubViews()requestData()}func setupSubViews() {view.addSubview(personView)}func requestData() {let person = Person(name: "godiscoder", image: "head_default", registerTimeStamp: 1480134638.0)let viewModel = PersonViewModel(person)personView.imageView.image = UIImage(named: viewModel.image)personView.nameLabel.text = viewModel.namepersonView.registerTimeLabel.text = viewModel.registerTimeStr}} 復制代碼好啦,到現在為止你已經實踐了MVVM的設計模式,如果不出意外的話你會在你的模擬器上顯示一個展示用戶信息的view,如下圖:
。5、當然,我們可以把給view賦值的語句放在PersonViewModel,這樣可以使代碼更加解耦。
// 在PersonViewModel 最下方 添加 extension PersonViewModel {func configurate(_ personView: PersonView) {personView.imageView.image = UIImage(named: image)personView.nameLabel.text = namepersonView.registerTimeLabel.text = registerTimeStr} }// 將 ViewController里的requestData()的代碼更新為下面的代碼func requestData() {let person = Person(name: "godiscoder", image: "head_default", registerTimeStamp: 1480134638.0)let viewModel = PersonViewModel(person)viewModel.configurate(personView) } 復制代碼完整代碼可以在這里下載。
總結
當你的項目業務比較簡單的時候還是推薦使用MVC架構,當業務比較復雜的時候可以轉為MVVM架構。
總結
以上是生活随笔為你收集整理的一看就懂的极简MVVM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [译] Fiber内幕:深入概述Reac
- 下一篇: GMQ发行稳定币将进一步打破稳定币市场垄