一看就懂的极简MVVM

栏目: IOS · 发布时间: 5年前

内容简介: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

为什么要使用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,如下图:

一看就懂的极简MVVM

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


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法设计与分析

算法设计与分析

郑宗汉//郑晓明 / 清华大学 / 2011-7 / 45.00元

《算法设计与分析(第2版)》系统地介绍算法设计与分析的概念和方法,共4部分内容。第1部分介绍算法设计与分析的基本概念,结合穷举法、排序问题及其他一些算法,对算法的时间复杂性的概念及复杂性的分析方法作了较为详细的叙述;第2部分以算法设计技术为纲,从合并排序、堆排序、离散集合的union和find操作开始,进而介绍递归技术、分治法、贪婪法、动态规划、回溯法、分支与限界法和随机算法等算法设计技术及其复杂......一起来看看 《算法设计与分析》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具