内容简介:Model-View-ViewModel(MVVM)是基于MVC的变形的一种设计模式,它由Model、View、ViewModel三部分组成,三部分的职责如下:具体逻辑如下图:当我们在项目初创时期,用MVC搭建项目是没有问题的。但是随着项目业务越来越多,越来越复杂的时候,我们会发现Controller里面的东西会非常的多,它通常会包含:Controller的生命周期函数、视图的响应事件、远程数据的获取,数据的变形,各种逻辑的判断等等。这样会导致代码阅读性下降,bug率提升。这也是为什么大家调侃MVC为Mas
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: String let image: String let registerTimeStamp: TimeInterval } 复制代码
2、接下来我们创建负责转换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 } } 复制代码
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.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") } } 复制代码
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.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,如下图:
。
5、当然,我们可以把给view赋值的语句放在 PersonViewModel
,这样可以使代码更加解耦。
// 在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架构。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。