Model-View-ViewModel(MVVM)是基於MVC的變形的一種設計模式,它由Model、View、ViewModel三部分組成,三部分的職責以下:git
struct
或者class
。官方推薦使用struct
定義Model。具體詳情可點擊這裏。class
,這樣它們就能夠經過引用指針來傳遞。具體邏輯以下圖:github
當咱們在項目初創時期,用MVC搭建項目是沒有問題的。可是隨着項目業務愈來愈多,愈來愈複雜的時候,咱們會發現Controller裏面的東西會很是的多,它一般會包含:Controller的生命週期函數、視圖的響應事件、遠程數據的獲取,數據的變形,各類邏輯的判斷等等。這樣會致使代碼閱讀性降低,bug率提高。這也是爲何你們調侃MVC爲Massive-View-Controller的緣由。swift
在這個背景下就誕生了MVVM設計模式來解決Massive Controller的問題,在使用MVVM的模式時,咱們能夠把數據轉換、數據邏輯判斷放在ViewModel
裏,以此來減輕Controller的負擔。設計模式
一、首先咱們新建一個項目,建立一個Person.swift
文件來表示用戶的數據:bash
//定義一個包含用戶名字、頭像和註冊時間的結構體當作用戶的Model
struct Person {
let name: String
let image: String
let registerTimeStamp: TimeInterval
}
複製代碼
二、接下來咱們建立負責轉換Model的ViewModel-PersonViewModel.swift
:架構
// name 和 image 只是簡單的經過兩個計算屬性來接受
// 將時間戳的註冊時間轉換爲字符串的註冊時間
class PersonViewModel {
let person: Person
private 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
}
}
複製代碼
三、建立展現用戶信息的PersonView.swift
:app
class PersonView: UIView {
let imageView = UIImageView()
let nameLabel = UILabel()
let registerTimeLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.brown
imageView.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 = .center
addSubview(nameLabel)
registerTimeLabel.frame = CGRect(x: 0, y: 110, width: frame.width, height: 16)
registerTimeLabel.font = UIFont.systemFont(ofSize: 14)
registerTimeLabel.textColor = UIColor.lightGray
registerTimeLabel.textAlignment = .center
addSubview(registerTimeLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
複製代碼
四、最後一步,在Controller中將它們鏈接起來:ide
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.white
setupSubViews()
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.name
personView.registerTimeLabel.text = viewModel.registerTimeStr
}
}
複製代碼
好啦,到如今爲止你已經實踐了MVVM的設計模式,若是不出意外的話你會在你的模擬器上顯示一個展現用戶信息的view,以下圖: 函數
。五、固然,咱們能夠把給view賦值的語句放在PersonViewModel
,這樣可使代碼更加解耦。ui
// 在PersonViewModel 最下方 添加
extension PersonViewModel {
func configurate(_ personView: PersonView) {
personView.imageView.image = UIImage(named: image)
personView.nameLabel.text = name
personView.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架構。