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架构。