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时,并且在某些时候,你可能还是使用子视图控制器去管理你所有的子视图会更好。
那么在哪里呢?他什么时候会有益于把事物分割和细化呢?请问,业务逻辑是否会验证用户的输入属于控制器,或者属于模型?
这里有很多模糊的线,似乎没有人能完全同意。当你画这些线的时候似乎没有问题,视图和其相应的控制器变得如此紧密而且耦合,那你还不如把他们看作是一个组件。
嘿!现在有一个主意…
在一个理想的世界,MVC可以很好的工作,然而,我们生活在一个真实的世界,事实也并非如此。现在,我们已经详细介绍了MVC打破典型用法的方法,让我们来看看另一种:模型 -
视图 -视图模型。
MVVM来自微软,但不要坚决反对使用它。MVVM和MVC非常相似。它让视图和控制器具有一定形式的紧密耦合的性质,并且还引入了一个新的组件。
在MVVM,视图和视图控制器正式形成连接;我们把他们作为一个组件。视图仍然没有对模型进行引用,但是也没有引用控制器。相反的,他们引用视图模型。
视图模型是作为用户输入验证逻辑的好地方,通过视图呈现逻辑,附加的网络请求,和其他复杂的代码。有一件事是,视图本身在视图模型中不属于任何视图的引用。视图模型中的这个逻辑对于iOS和OS
X中应该是同样适用的。(换一种说法,不要在你的视图模型中#import UIKit.h,你会被罚款的)。
由表现逻辑,比如映射一个模型值去格式化一个东西--属于视图模型中,视图控制器本身会变得很大,但是并非臃肿。最好的部分是当你使用MVVM,你可以放置一小部分逻辑在你的视图模型中,当你成为越来越适合的范例时再把它们迁移过来。
使用MVVM编写的iOS应用程序是高度可测试的;因为视图模型包含了所有的演示逻辑并且不引用这个视图,它可以通过编程进行全面测试。虽然很多黑客参与测试Core
Data模型,但是使用MVVM编写的应用程序完全可以进行单元测试。
在我的经验中,使用MVVM的结果是,代码的总量略有增加,但在代码的复杂性部分整体下降。这是一个权衡过后很核算的方法。
如果你再回头看看MVVM图解,你会发现,我用了模棱两可的动词“通知”和“更新”,但是没有支出应该怎么做。你可以用KVO,就像MVC,但是很快就会变得很难管理。在实践中,使用ReactiveCocoa是把所有模块粘合在一起的一个好方法。
如果你已经开发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是把所有模块粘合在一起的一个好方法。
相关文章推荐
- Xamarin.iOS + MvvmCross - Notes about how to use Mvx TableViewSource
- 同样的布局,在4 5上没问题,但是5s 6 6s 6p都有问题
- iOS动态修复App线上Bug 之 JSPatch
- iOS对键盘的处理
- iOS - 静态库的创建与使用
- 将BIOS输出重定向到串口
- IOS图片无限轮播器的实现原理
- 一个自定义的ActionSheet,可以自已轻松修改上面的东西
- iOS应用程序的生命周期
- 10大iOS开发者最喜爱的类库
- ios线程的五种使用方式
- CocoaPods的安装使用和常见问题
- 如何使用iOS 开发证书 和 Profile 文件
- iOS 正则表达式(身份证号详细验证和粗略验证两种表示,后期会持续添加)
- ionic集成极光推送插件-iOS
- ios监听静音键和音量键事件
- iOS开发之打电话,发短信,发送邮件
- iOS下JS与原生OC互相调用
- iOS开发-环信单聊实现
- iOS - 自定义启动图