MVC替代品[第1部分:MVVM]

Model View Controller是我在iOS开发中学习的第一个概念。 您可以在iOS应用中看到最常用的设计模式。 苹果公司建议,它易于使用,并且相当容易理解。

如果您已经注意到有许多其他架构可以替代MVC。 在这里,我们将看到一个实用的列表,更重要的是这个问题的答案。

为什么MVC需要替代方案?

在MVC中,模型代表为该应用程序指定的数据模型。 视图是用户看到的应用程序的一部分。 控制器充当视图对象及其模型对象之间的中介。 它负责使模型相对于用户与View的交互保持更新,并负责通过Model的更改来更新View。 View会通知控制器任何用户交互。 然后,视图控制器更新模型以反映状态的变化。

按照定义,它们听起来是分开的,但实际上View和controller是紧密耦合的,而且每个人都知道另外两个。 这是所有问题开始的地方:

  1. 这违反了单一责任原则
  2. 这导致了一个普遍的问题,即所谓的Massive View Controller
  3. 这降低了每个实体的可重用性
  4. 代码的可测试性几乎是不可能的

在现实生活中,视图和模型是分开的,但是视图和控制器是紧密耦合的。 控制器和视图的所有代码都写在ViewController中。 View Controller可以快速将代码打包以用于各种目的。 这个问题称为Massive View Controller

Massive View Controller处于一种状态,许多逻辑和职责(例如网络连接,将Date转换为String和图像处理代码)已移入View Controllers。 这种做法会使您的代码庞大且难以更改。 它们显然不属于这里,但是我们应该将它们视为模型的一部分吗? 没有! 他们当然不是观点。 他们还能在哪里?


模型视图ViewModel在View和Model之间引入了另一个组件ViewModel。 该特殊层的主要目的是将数据状态从视图控制器移动到ViewModel(MVVM将视图和控制器都视为View ,并将视图控制器视为View)。

出于几个原因,MVVM成为了流行的iOS体系结构。 它着重于将用户界面与其他层分开。 MVVM与您现有的MVC架构兼容。 这种分离使应用程序更具可测试性,因为ViewModel对View一无所知。

通过使用MVVM,您可以将整个业务逻辑与曾经在MVC中耦合的UIKit分开。

视图模型

ViewModel是UIKit独立的视图及其状态的表示。 它从视图接收用户交互,从模型中获取数据,然后将数据处理为一组准备显示的属性。 这些属性中的每一个都代表视图中的UI组件。

有关为UI准备数据的所有逻辑(例如,将日期转换为字符串)发生在ViewModel中,而不是View中。 因此,可以为这些逻辑编写更简单的测试,而无需了解View的实现。

在MVVM中,没有直接在View中进行任何更改,我们在ViewModel中处理业务逻辑,因此View也会相应更改。 在观察ViewModel的更改后,View会自动更新。 将UI组件连接到ViewModel属性称为“绑定”。

捆绑

绑定是指视图和viewModel之间的数据流。 对于视图中的每个属性,viewModel中存在一个对应的属性,该属性将针对该UI元素进行更新。 假设我们的视图有一个UITextField,对于文本字段中的每个新按键,viewModel中的对应对象将立即更新。 这应该是双向绑定,这意味着viewModel属性的更改也将反映在视图上。

理解MVVM的重要部分是View通过某种观察者从ViewModel更新其状态。 基本上,整个想法是将ViewModel中的任何状态更改通知给View。

有一些实现此目的的选项(在Swift中):

  • 功能性反应式编程,例如RxSwift或ReactiveCocoa
  • 像Bond这样的Swift KVO库
  • 使用自制解决方案

关于MVVM,没有什么可以强迫您使用特定的机制来更新viewModel或视图,但是通常,如果您在谈论MVVM,则想到的第一个解决方案就是功能响应式编程。

如果您有使用功能性反应式编程的经验,或者熟悉诸如ReactiveCocoa之类的框架,则与将属性绑定到信号完全相同。 对于MVVM,视图会将viewModel的属性绑定到UI元素。

TL; DR

在MVVM中,ViewModel封装了视图可以绑定到的属性。 MVVM让我们将控件状态绑定到视图模型。 例如,如果我们有一个需要更改其标题文本的按钮,则该按钮应将其标题绑定到viewModel中的相应属性。

使用MVVM可以解决Massive视图控制器问题(并非总是如此!因为viewModel本身可能会变得笨重),将业务逻辑与UIKit分开,并使代码更易于维护和测试。


iOS架构模式-揭开MVC,MVP,MVVM和VIPER的神秘面纱
如何不急于MVVM实现
MVVM简介
具有ReactiveCocoa的基本MVVM