您的位置:首页 > 移动开发 > IOS开发

iOS设计模式--MVVM

2016-03-31 11:46 477 查看
原文网址:http://www.teehanlax.com/blog/model-view-viewmodel-for-ios/

如果你已经开发iOS应用程序有一段时间了,那么你可能听说过MVVM或者MVC(设计模式)。这是你构建iOS应用程序的标准模式。然而,最近,我越来越厌倦MVC的一些缺点了。在这篇文章中,我要梳理一下什么是MVC,及其缺点,并告诉你一个新的方式来组织你的应用程序:(那就是)MVVM。

Model-View-Controller--MVC(模型-视图-控制器)
MVC是通过明确的范例来构造你的代码,Apple甚至是这么说的。在MVC模式下,所有的对象被划分为模型,视图和控制器。模型存放数据,视图提供了一个交互式的界面给用户,视图控制器协调模型和视图之间的相互作用。



在图解里,视图作为通知任何用户交互的控制器。然后视图控制器更新模型来体现状态的变化。然后该模型(通常是通过键 - 值观察)通知所有控制器,他们需要对自己的视图进行更新。这种协调方式构成了很多写在iOS应用程序里面的代码。

模型对象通常是非常,非常简单的。很多时候,他们是核心数据管理对象,或者,如果你比较喜欢避开核心数据和其他普遍的模型。更具苹果的说法,模型用包含的数据和逻辑来处理这些数据。在实践中,模型往往很稀疏,不管这样是好是坏,控制器得到了模型的逻辑。

视图(通常情况下)是UIKit组件或者程序员定义的UIKit组件集合其中之一。他们通常拼凑到你的.xib或者.Storyboard中:视觉和应用程序交互的组件。按钮。标签。你有一个想法,视图应该永远不会被模型直接引用,控制器应该只通过IBAction触发事件。不属于视图本身的业务逻辑不应该在那里。

就这样我们舍弃了控制器。控制器是一个应用程序的“粘合剂代码”:它在模型和视图之间协调所有的交互,控制器负责管理他们自己视图的视图层次结构。他们响应视图的加载,出现,消失等等。他们倾向于用模型逻辑来装载,我们避免我们的模型和业务逻辑远离我们的观点。这是我们与MVC的第一个问题…

大规模的视图控制器

因为在视图控制器中放置的代码量非常大,他们往往会变得很臃肿,在iOS中有的视图控制器中的代码,可能会延展至成千上万代码行。你应用程序中这些臃肿的片段权衡下来:大规模的视图控制器都难以维持(因为他们的规模太庞大),其中含有很多属性,会让他们的状态很难被管理,又符合许多协议,混合了协议的响应代码与控制器的逻辑。

大规模的视图控制器是很难测试的,不管是手动测试还是单元测试,因为他们有很多可能的状态。把你的代码分割的更少,更小更简单通常是一件很好的事情。

缺少网络逻辑

MVC的定义 - 苹果使用的那个 - 规定所有对象可以被分类为一个类型,一个视图,或者一个控制器。所有这些。所以,你应该吧网络代码放在哪里呢?而代码与API的通信又在哪里呢?

你可以试着巧妙的把它放在模型对象里,但是这么做可能会变得很棘手,因为网络调用应该是异步的过程。所以,如果一个网络请求会超越拥有它的模型,好吧,它变复杂了。你绝对不应该把网络代码放进视图里,所以…应该留给控制器来处理。这是一个不好的想法,因为它会促使我们产生大规模的视图控制器这个问题。

那么,在哪里呢?对于代码来说,MVC的这三个组成部分没有一个地方不适合代码。


可测性差

MVC还有另外一个大问题就是,它不鼓励开发者编写测试用例。自从视图控制器视图操作逻辑与业务逻辑混合,把这些单元测试分开就成了一项艰巨的任务。都赞成忽视这个任务(单元测试)…所以就没有测试任何东西。

“Manage”的模糊定义

我前面提到的那个视图控制器来管理视图层次的部分,视图控制器有一个“视图”属性,并且可以通过IBOutLets访问该视图的子视图。这样的扩展就不太好,因为当你有很多outlets时,并且在某些时候,你可能还是使用子视图控制器去管理你所有的子视图会更好。

那么在哪里呢?他什么时候会有益于把事物分割和细化呢?请问,业务逻辑是否会验证用户的输入属于控制器,或者属于模型?

这里有很多模糊的线,似乎没有人能完全同意。当你画这些线的时候似乎没有问题,视图和其相应的控制器变得如此紧密而且耦合,那你还不如把他们看作是一个组件。

嘿!现在有一个主意…


Model-View-ViewModel(MVVM)

在一个理想的世界,MVC可以很好的工作,然而,我们生活在一个真实的世界,事实也并非如此。现在,我们已经详细介绍了MVC打破典型用法的方法,让我们来看看另一种:模型 -
视图 -视图模型。

MVVM来自微软,但不要坚决反对使用它。MVVM和MVC非常相似。它让视图和控制器具有一定形式的紧密耦合的性质,并且还引入了一个新的组件。



在MVVM,视图和视图控制器正式形成连接;我们把他们作为一个组件。视图仍然没有对模型进行引用,但是也没有引用控制器。相反的,他们引用视图模型。

视图模型是作为用户输入验证逻辑的好地方,通过视图呈现逻辑,附加的网络请求,和其他复杂的代码。有一件事是,视图本身在视图模型中不属于任何视图的引用。视图模型中的这个逻辑对于iOS和OS
X中应该是同样适用的。(换一种说法,不要在你的视图模型中#import UIKit.h,你会被罚款的)。

由表现逻辑,比如映射一个模型值去格式化一个东西--属于视图模型中,视图控制器本身会变得很大,但是并非臃肿。最好的部分是当你使用MVVM,你可以放置一小部分逻辑在你的视图模型中,当你成为越来越适合的范例时再把它们迁移过来。

使用MVVM编写的iOS应用程序是高度可测试的;因为视图模型包含了所有的演示逻辑并且不引用这个视图,它可以通过编程进行全面测试。虽然很多黑客参与测试Core
Data模型,但是使用MVVM编写的应用程序完全可以进行单元测试。

在我的经验中,使用MVVM的结果是,代码的总量略有增加,但在代码的复杂性部分整体下降。这是一个权衡过后很核算的方法。

如果你再回头看看MVVM图解,你会发现,我用了模棱两可的动词“通知”和“更新”,但是没有支出应该怎么做。你可以用KVO,就像MVC,但是很快就会变得很难管理。在实践中,使用ReactiveCocoa是把所有模块粘合在一起的一个好方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: