在iOS开发过程中,MVC的使用可谓是众所周知,作为iOS开发人员也都经常使用这个模式。在MVC下,所有的对象都被归类成一个Model、一个View、一个Controller。虽然现在MVC仍然是主流的框架,但是它也被慢慢的替换成MVVM,因为越来越多的开发人员调侃MVC为Massive View Controller。

一、MVVM

MVVM是Model-View-ViewModel的简写。微软的WPF带来了新的技术体验,如Silverlight、音频、视频、3D、动画…..,这导致了软件UI层更加细节化、可定制化。同时,在技术层面,WPF也带来了诸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View-ViewModel)框架的由来便是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架。它立足于原有MVP框架并且把WPF的新特性糅合进去,以应对客户日益复杂的需求变化。

%title插图%num
一种可以很好地解决Massive View Controller问题的办法就是将Controller 中的展示逻辑抽取出来,放置到一个专门的地方,而这个地方就是ViewModel 。MVVM衍生于MVC,是对 MVC 的一种演进,它促进了UI代码与业务逻辑的分离,而且正式规范了视图和控制器紧耦合的性质,并引入新的组件。
在MVVM中,View和View Controller是联系在一起,可以把它们视为一个组件,View和View Controller都不能直接引用Model,而是通过引用视图模型(ViewModel),ViewModel是一个放置用户输入验证逻辑、视图显示逻辑、发起网络请求和其他代码的地方,使用MVVM会轻微的增加代码量,但总体上减少了代码的复杂性、耦合性。
二、MVVM设计模式模块

由于WPF技术出现,使得MVP设计模式有所改进,MVVM模式便是使用的是数据绑定基础架构。它们可以轻松构建UI的必要元素。可以参考The Composite Application Guidance for WPF(prism),View绑定到ViewModel,然后执行一些命令再向它请求一个动作。然而又反过来,ViewModel再跟Model通讯,告诉它更新来响应UI。这样便为应用构建UI非常的简单容易。给一个应用程序上贴一个界面越容易,外观设计师就越容易使用Blend来创建一个漂亮的界面。同时,当UI和功能越来越低耦合的时候,功能的可测试性就越来越强。
在MVP模式中,为了让UI层能够从逻辑层上分离下来,设计师们在UI层与逻辑层之间加了一层interface。无论是UI开发人员还是数据开发人员,都要尊重这个契约,按照它进行设计和开发。这样,理想状态下,无论是Web UI还是Window UI就都可以使用同一套数据逻辑了。借鉴MVP的IView层养成习惯,View Model听起来比Presenter要贴切得多;会把一些跟事件、命令相关的东西放在MVC的’C’,或者是MVVM的’VM’。
三、MVVM的优缺点

(一)MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点:
1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。
4. 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

%title插图%num
(二)MVVM模式的缺点:
1.数据绑定使得Bug很难被调试。如果界面发生错误,有可能是View的代码有问题,也有可能是Model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,要想定位原始出问题的地方,就变得不那么容易了。
2.对于大型项目,数据绑定和数据转化需要花费更多的内存(成本)。主要在于:数组内容的转化成本较高:数组里面每项都要转化成Item对象,如果Item对象中还有类似数组,就很头疼。转化之后的数据在大部分情况是不能直接被展示的,为了能够被展示,还需二次转化。只有在API返回的数据高度标准化时,这些对象原型(Item)的可复用程度才高,否则容易出现类型膨大,提高维护成本。
3.调试时通过对象原型查看数据内容,不如直接通过NSDictionary或者NSArray这样直观。
4.同一API的数据被不同View展示时,难以控制数据转化的代码,它们有可能会散落在任何需要的地方。

%title插图%num

四、MVVM模式的其他内容

1.使用MVVM来开发控件。由于控件在大部分情况下不涉及到数据的持久化,所以如果将M纯粹理解为DomainModel的话,使用MVVM模式来进行自定义控件开发,实际上可以省略掉M,变成了VVM。

2.View可以引用ViewModel,但反过来不行(即:不要在ViewModel中引入#import UIKit.h,任何视图本身的引用都不能放在ViewModel中),ViewModel可以引用Model,但反过来不行。
3.MVVM可以兼容当前你使用的MVC架构,也可以增加你开发的应用的可测试性;MVVM配合一个绑定机制效果*好(eg:ReactiveCocoa)。
4.ViewController尽量不要涉及业务逻辑,让ViewModel去做业务逻辑;ViewController 只是一个“中间人”,接收View的事件、调用ViewModel的方法、响应ViewModel的变化;ViewModel *不能包含视图View(UIKit.h),否则就跟View产生耦合,不方便复用和测试。
5.ViewModel之间可以有依赖;ViewModel要避免过于臃肿冗余,否则讲重蹈Controller的覆辙,变得难以维护。

%title插图%num

五、MVVM模式总则

MVC的设计模式也并非是必须摒弃的架构,*低目前MVC设计模式仍是iOS开发的主流框架。MVVM是MVC的升级版,完全兼容当前的MVC架构,MVVM虽然促进了UI 代码与业务逻辑的分离,一定程度上减轻了ViewController的耦合度,但是View和ViewModel之间的数据绑定,使得MVVM变得复杂和难用了,如果不能处理和驾驭二者间的数据绑定,仍然会造成Controller代码过于复杂冗余、代码逻辑不易维护的问题。
一个轻量级的ViewController是基于MVC和MVVM模式进行代码职责的分离而打造的。MVC和MVVM优缺点共存,但是优点产生的效果远远盖住了缺点的不良影响,它们的低耦合性、封装性、可测试性、可维护性和多人协作便利等优势大大提高了开发效率。只要处理协调好二者之间的矛盾,就能很好的驾驭它们。