iOS 应用架构设计详解
在介绍应用架构之前,先来看看目前iOS上最基础的架构MVC,以及为解决MVC的毛病而诞生的其他几个架构,如MVVM。
Cocoa的很多技术跟架构都是基于MVC。而且无论是文档、示例代码,还是创建一个项目时提供的模版代码,Apple都鼓励开发者去使用MVC。MVC定义了App里对象的角色(Model-View-Controller),以及它们之间的交互方式:
1、Model: 表示业务数据对象
2、View: 展示数据的UI
3、Controller: Model跟View之间的粘合剂。一方面对View上的行为作出反应,通常会涉及到Model的更改;另一方面将Model的改动反应到View上
由于Controller作为粘合剂的存在,View 和 Model 只需要跟 Controller 交互,而不知道另一方的存在。这样,View 和 Model 作为独立可复用的组件,Controller 里处理业务逻辑。听起来这样的架构很清晰直观,实际应用中,MVC 对于不是很复杂的 App 也是非常高效的。但对稍复杂些的App,MVC 使用起来就会非常吃力。
你可能听过 MVC 也被简称为 Massive View Controller,这就是原因所在 - View Controller 承担的责任太多:
1、网络请求
2、数据访问和存储
3、UI的调整和组合
4、业务逻辑
5、View 的 delegate、data source
6、状态的维护
与单一责任准则背道而驰。过于臃肿的 View Controller 使 App 的维护成本非常高。我们的第一个项目有数刚接手时就是这个样子,尽管我们已经把网络请求以及数据访问和存储放到了 Model 里,但由于对象边界的定义不够清晰,大部分 View Controller 依然很臃肿,上千行的 View Controller 很常见。 关于 View Controller 有个准则:如果一个 View Controller 超过了 300 行代码,那它一定做了责任范围以外的事。更不幸的是由于一些职责移交给 Model,导致 Model 也变得臃肿起来。原来唯一可以做 Unit Test 的 Model 现在测试也很困难。
为解决 MVC的问题,MVVM、VIPER等架构应运而生。
MVVM架构: MVVM的出现主要是为了解决在开发过程中 Controller 越来越庞大的问题,变得难以维护,所以 MVVM 把数据加工的任务从 Controller 中解放了出来,使得 Controller 只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让 View 响应 ViewModel 的改变。
MVVM是基于胖Model的架构思路建立的,然后在胖Model中拆分两部分:Model和ViewModel。 ViewModel 本质上算是Model层(因为是胖 Model 里面分出来的一部分),所以 View 并不适合直接持有 ViewModel,因为 ViewModel 有可能并不是只服务于特定的一个View,使用更加松散的绑定关系能够降低 ViewModel和View 之间的耦合度。
还有一个让人恨容易忽略的问题,大部分国外资料阐述MVVM的时候都是这样排布的:
1
|
ViewViewModel Model |
造成了 MVVM 不需要 Controller 的错觉,现在似乎发展成业界开始出现 MVVM 是不需要 Controller 的声音了。其实 MVVM 是一定需要 Controller 的参与的,虽然 MVVM 在一定程度上落化了 Controller 的存在感,并且给 Controller 做了减负瘦身(这也是 MVVM 的主要目的)。但是,这并不代表 MVVM 中不需要 Controller, MMVC和MVVM他们之间的关系
应该是这样:
1
|
View C ViewModel Model |
所以使用 MVVM 之后,就不需要 Controller 的说法是不正确的。严格来说 MVVM 其实是 MVCVM。从中可以得知,Controller夹在 View 和 ViewModel 之间做的其中一个主要事情就是将View和ViewModel进行绑定。在逻辑上,Controller 知道应当展示哪个View,Controller也知道应当使用那个 ViewModel,然而 View和ViewModel 它们之间是相互不知道的,所以 Controller 就负责控制他们的绑定关系,所以叫Controller/控制器就是这个原因。
前面扯了那么多,其实归根结底就是一句话:在MVC的基础上,把c拆出一个ViewModel专门负责数据处理的事情,就是 MVVM。然后,为了让 View 和 ViewModel 之间能够有比较松散的绑定关系,于是我们使用 ReactiveCocoa,KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。
MVVM(View-ViewManger-C-ViewModel-Model)
1、View - 用来呈现用户界面
2、ViewManger - 用来处理 View 的常规事件,负责管理View
3、Controller - 负责 ViewManger和ViewModel 之间的绑定,负责控制器本身的生命周期。
4、ViewModel - 存放各种业务逻辑和网络请求
5、Model - 用来呈现数据
这种设计的目的是保持 View和Model 的高度纯洁,提高可扩展性和复用度。在日常开发中,ViewModel是为了拆分 Controller 业务逻辑而存在的,所以 ViewModel 需要提供公共的服务接口,以便于 Controller 提供数据。而 ViewManger 的作用相当于一个小管家,帮助 Controller 来分别管理每个 subView,ViewManger 负责接管来自 View 的事件,也负责接收来自 Controller 的模型数据,而 View 进行自己所负责的视图数据绑定工作。Controller 则是最后的大家长,负责将 ViewModel和ViewManger进行绑定,进行数据转发工作。把合适的数据模型分发给合适的视图管理者。