如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller,即MVC。MVC是构建iOS App的标准模式。然而,最近我已经越来越厌倦MVC的一些缺点。在本文,我将重温一下MVC是什么,详述它的缺点,并且告诉你一个新的方式来架构你的 App:Model-View-ViewModel。拿出你的流行语bingo card(宾果卡,一种游戏卡片-译者注),因为我们即将进行一次范式转变。
Model-View-Controller
Model-View-Controller是一个用来组织代码的权威范式。Apple甚至是
这么说的。在MVC下,所有的对象被归类为一个model,一个view,或一个controller。Model持有数据,View显示与用户交互的界面,而View Controller调解Model和View之间的交互。
在上图中,view将用户交互通知给controller。view controller通过更新model来反应状态的改变。model(通常使用Key-Value-Observation)通知controller 来更新他们负责的view。大多数iOS应用程序的代码使用这种方式来组织。
模型model的对象通常非常非常的简单。很多时候,他们就是Core Data
managed objects,或者避免使用Core Data,就是其他
流行的数据模型层。根据Apple的文档,model包括数据和操作数据的业务逻辑。在实践中,model层往往非常薄,不管怎样,model层的业务逻辑被拖入了controller。
视图view通常是UIKit控件(component,这里根据习惯译为控件)或者编码定义的UIKit控件的集合。进入.xib或者 Storyboard会发现一个app、Button、Label都是由这些可视化的和可交互的控件组成。你懂的。View不应该直接引用model,并 且仅仅通过IBAction事件引用controller。业务逻辑很明显不归入view,视图本身没有任何业务。
还有控制器controller。Controller是app的“胶水代码”:协调模型和视图之间的所有交互。控制器负责管理他们所拥有的视 图的视图层次结构,还要响应视图的loading、appearing、disappearing等等,同时往往也会充满我们不愿暴露的model的模型 逻辑以及不愿暴露给视图的业务逻辑。这引出了第一个关于MVC的问题...
厚重的View Controller
由于大量的代码被放进view controller,导致他们变的相当臃肿。在iOS中有的view controller里绵延成千上万行代码的事并不是前所未见的。这些超重app的突出情况包括:厚重的View Controller很难维护(由于其庞大的规模);包含几十个属性,使他们的状态难以管理;遵循许多协议(protocol),导致协议的响应代码和 controller的逻辑代码混淆在一起。
厚重的view controller很难测试,不管是手动测试或是使用单元测试,因为有太多可能的状态。将代码分解成更小的多个模块通常是件好事。
遗失的网络逻辑
苹果使用的MVC的定义是这么说的:所有的对象都可以被归类为一个model,一个view,或是一个controller。就这些。那么把网络代码放哪里?和一个API通信的代码应该放在哪儿?
你可能试着把它放在model对象里,但是也会很棘手,因为网络调用应该使用异步,这样如果一个网络请求比持有它的model生命周期更长,事 情将变的复杂。显然也不应该把网络代码放在view里,因此只剩下controller了。这同样是个坏主意,因为这加剧了厚重View Controller的问题。
那么应该放在那里呢?显然MVC的3大组件根本没有适合放这些代码的地方。
较差的可测试性
MVC的另一个大问题是,它不鼓励开发人员编写单元测试。由于view controller混合了视图处理逻辑和业务逻辑,分离这些成分的单元测试成了一个艰巨的任务。大多数人选择忽略这个任务,那就是不做任何测试。
定义模糊的“Manage”
之前我提到了view controller可以管理试图的层次结构;view controller有一个“view”属性,并且可以通过IBOutlet访问视图的任何子视图。当有很多outlet时这样做不易于扩展,在某种意义 上,最好不要使用子视图控制器(child view controller)来帮助管理子视图(subview)。
要点在哪?验证用户输入的业务逻辑应归入controller还是model呢?
在这里有多个模糊的标准,似乎没有人能完全达成一致。貌似无论如何,view和对应的controller都紧紧的耦合在一起,总之,还是会把它们当成一个组件来对待。
Hey!现在有个点子...
Model-View-ViewModel
在理想的世界里,MVC也许工作的很好。然而,我们生活在真实的世界。既然我们已经详细说明了MVC在典型场景中的问题,那让我们看一看一个可供替换的选择:Model-View-ViewModel。
MVVM
来自微软,不过不要坚持反对它。MVVM和MVC很像。它正式规范了视图和控制器紧耦合的性质,并引入新的组件。
在MVVM里,view和view controller正式联系在一起,我们把它们视为一个组件。视图view仍然不能直接引用模型model,当然controller也不能。相反,他们引用视图模型view model。
view model是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。有一件事情不应归入view model,那就是任何视图本身的引用。view model的概念同时适用于于iOS和OS X。(换句话说,不要在view model中使用 #import UIKit.h)
由于展示逻辑(presentation logic)放在了view model中(比如model的值映射到一个格式化的字符串),视图控制器本身就会不再臃肿。当你开始使用MVVM的最好方式是,可以先将一小部分逻辑放 入视图模型,然后当你逐渐习惯于使用这个范式的时候再迁移更多的逻辑到视图模型中。
使用MVVM的iOS app是高度可测试的;因为view model包含了所有的展示逻辑并且不会引用view,所以它可以通过编程方式充分测试。虽然有
众多的hack技术参与到测试Core Data模型,但使用MVVM写的app可以进行充分的单元测试。
以我的经验,使用MVVM会轻微的增加代码量,但总体上减少了代码的复杂性。这是一个划算的交易。
回过头再来看MVVM的图示,你会注意到我使用了模糊的动词“notify”和“update”,而没有详细说明该怎么做。你可以使用KVO,就像MVC那样,但这很快就会变得难以管理。事实上,
使用ReactiveCocoa会是更好的方式来组织各个部分。
- 用Model-View-ViewModel构建iOS App(转)
转载自 Model-View-ViewModel for iOS [译] 如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller, 即MVC.MVC是构建iOS a ...
- ios app开发步骤
虽然开发一个app的任务看上去可能很艰巨,但是整个过程可以抽象成几个相对简单的步骤,下面这些步骤会在你开发第一个app时帮你步入正途. 定义Concept 每个好app都是从一个concept开始. ...
- 用Xamarin和Visual Studio编写iOS App
一说开发 iOS app,你立马就会想到苹果的开发语言 Objective C/Swift 和 Xcode.但是,这并不是唯一的选择,我们完全可以使用别的语言和框架. 一种主流的替换方案是 Xamar ...
- 【IOS笔记】Using View Controllers in Your App
参考:http://www.cnblogs.com/patientAndPersist/p/3279645.html Using View Controllers in Your App Whethe ...
- 关于报错:'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based
最近在看Extension相关知识的时候,自己写了个小demo 发现[UIApplication sharedApplication]这个方法敲不出来了, 总是报错:'sharedApplicatio ...
- iOS9中找不到XXX.dylib 与 is unavailable no availabel on ios (app extension) - use view controller 的解决办法
在 iOS9 中现在找不到 XXX.dylib 了,比如libz.tbd 如果要用到 libz.dylib,可以用下面的办法,来自 Stack Overflow. Go to Build Phase ...
- iOS App开发的那些事儿2:如何搭建合适的框架
<iOS App开发的那些事儿>系列文章从更宏观的角度出发,不仅仅局限于具体某个功能.界面的实现,而是结合网易云信iOS端研发负责人多年的经验,从如何优化现有代码的角度出发,深度分析如何创 ...
- iOS App开发那些事:如何选择合适的人、规范和框架?
http://www.cocoachina.com/ios/20141202/10386.html 自从做Team Leader之后,身上权责发生了变化,于是让我烦恼的不再是具体某个功能,某个界面的实 ...
- Qt Model/View(官方翻译,图文并茂)
http://doc.trolltech.com/main-snapshot/model-view-programming.html 介绍 Qt 4推出了一组新的item view类,它们使用mode ...
随机推荐
- linux命令-系统命令
1.查看Linux磁盘空间大小 df -lh Filesystem 容量 已用 可用 已用% 挂载点 /dev/hda8 11G 6.0G 4.4G 58% / /dev/shm 236M 0 236 ...
- [原]使用node-mapnik生成openstreetmap-carto风格的瓦片
上回说到如何在CentOS上部署node-mapnik,本想着接下来学习如何使用node-mapnik生成openstreetmap的瓦片图,没想到在接下来的近40天的时间里忙成了狗!好不容易等到元旦 ...
- 如何在ASP.NET Core中实现CORS跨域
注:下载本文的完整代码示例请访问 > How to enable CORS(Cross-origin resource sharing) in ASP.NET Core 如何在ASP.NET C ...
- HttpURLConnection类
导语 java.net.HttpURLConnectin类是URLConnection类的抽象子类.它在处理协议为HTTP的URL时特别有效.具体而言,它通过它可以获取和设置请求方法,确定是否重定向, ...
- Doc
一:window: 属性(值或者子对象):opener:打开当前窗口的源窗口,如果当前窗口是首次启动浏览器打开的,则opener是null,可以利用这个属性来关闭源窗口. 方法(函数):事件(事先设置 ...
- Less的使用
Less为css预处理器 首先先去下载一个koala编译器软件,然后运行打开 新建一个项目目录,在css文件夹中新建一个后缀为less的文件,然后拉入koala软件中,然后运行 ,你的css文件夹中就 ...
- 用 ElementTree 在 Python 中解析 XML
用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...
- Android自定义九宫格图案解锁
转自: http://blog.csdn.net/shineflowers/article/details/50408350
- css中,设置百分比后,让百分比的宽度包括padding和border来计算
*{ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;}
- 【codeforces 148D】 Bag of mice
http://codeforces.com/problemset/problem/148/D (题目链接) 题意 包中有w个白鼠,b个黑鼠.公主和龙轮流画老鼠,公主先画,谁先画到白鼠谁就赢.龙每画完一 ...