iOS 关于MVC MVVM的理解(一)

原文地址: http://casatwy.com/iosying-yong-jia-gou-tan-viewceng-de-zu-zhi-he-diao-yong-fang-an.html

一. MVC

            1. MVC(Model-View-Controller)其中Model就是作为数据管理者View作为数据展示者Controller作为数据加工者ModelView又都是由Controller来根据业务需求调配,所以Controller还负担了一个数据流调配的功能.

    

M应该做的事:


  1. 给ViewController提供数据
  2. 给ViewController存储数据提供接口
  3. 提供经过抽象的业务基本组件,供Controller调度

C应该做的事:


  1. 管理View Container的生命周期
  2. 负责生成所有的View实例,并放入View Container
  3. 监听来自View与业务有关的事件,通过与Model的合作,来完成对应事件的业务。



V应该做的事:


  1. 响应与业务无关的事件,并因此引发动画效果,点击反馈(如果合适的话,尽量还是放在View去做)等。
  2. 界面元素表达

二.MVCS

     苹果自身就采用的是这种架构思路,从名字也能看出,也是基于MVC衍生出来的一套架构。从概念上来说,它拆分的部分是Model部分,拆出来一个Store。这个Store专门负责数据存取。但从实际操作的角度上讲,它拆开的是Controller。

这算是瘦Model的一种方案,瘦Model只是专门用于表达数据,然后存储、数据处理都交给外面的来做。MVCS使用的前提是,它假设了你是瘦Model,同时数据的存储和处理都在Controller去做。所以对应到MVCS,它在一开始就是拆分的Controller。因为Controller做了数据存储的事情,就会变得非常庞大,那么就把Controller专门负责存取数据的那部分抽离出来,交给另一个对象去做,这个对象就是Store。这么调整之后,整个结构也就变成了真正意义上的MVCS。

关于胖Model和瘦Model

  • 什么叫胖Model?


胖Model包含了部分弱业务逻辑。胖Model要达到的目的是,Controller从胖Model这里拿到数据之后,不用额外做操作或者只要做非常少的操作,就能够将数据直接应用在View上(对拿到的数据进行简单的业务逻辑处理, 返回可以直接用的值), 把弱业务代码放到model中处理, 会给controller瘦身, Controller只需要处理强逻辑业务, 一般情况下,强业务变动的可能性要比弱业务大的多, 弱业务相对稳定,所以弱业务塞进Model里,弱业务重复出现的频率要大于强业务,对复用性的要求更高,所以在model中处理会更合适, 如果在Controller中处理会有很多冗余的代码(相同重复的), 如果弱业务有改动的话, 在model一个地方改变就好, 其他需要的地方也就跟着改变了.

然而其缺点就在于,胖Model相对比较难移植,虽然只是包含弱业务,但好歹也是业务,迁移的时候很容易拔出萝卜带出泥,FatModel很有可能随着软件的成长越来越Fat,最终难以维护。

  • 什么叫瘦Model?


瘦model跟业务无关, 它的数据可以交给任何一个能处理它的数据的Helper或者Controller, model只是数据表达, 容易维护.但是话又说回来, model的操作会出现在各种地方(到处都是)Controller会变得很膨胀, 一处改, 所有涉及到的都需要改动.


最后, MVCS是基于瘦Model的一种架构思路,把原本Model要做的很多事情中的其中一部分关于数据存储的代码抽象成了Store,在一定程度上降低了Controller的压力。


三.MVVM

在ReactiveCocoa这个库成熟之后,ViewModel和View的信号机制在iOS下终于有了一个相对优雅的实现。MVVM本质上也是从MVC中派生出来的思想,MVVM着重想要解决的问题是尽可能地减少Controller的任务。不管MVVM也好,MVCS也好,他们的共识都是Controller会随着软件的成长,变很大很难维护很难测试。只不过两种架构思路的前提不同,MVCS是认为Controller做了一部分Model的事情,要把它拆出来变成Store,MVVM是认为Controller做了太多数据加工的事情,所以MVVM把数据加工的任务从Controller中解放了出来,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。(说白了就是把controller中的一些功能代码拆分出来成单独的类).


MVVM是基于胖Model的架构思路建立的,然后在胖Model中拆出两部分:Model和ViewModel关于这个观点我要做一个额外解释:胖Model做的事情是先为Controller减负,然后由于Model变胖,再在此基础上拆出ViewModel,跟业界普遍认知的MVVM本质上是为Controller减负这个说法并不矛盾,因为胖Model做的事情也是为Controller减负。

另外,我前面说MVVM把数据加工的任务从Controller中解放出来,跟MVVM拆分的是胖Model也不矛盾。要做到解放Controller,首先你得有个胖Model,然后再把这个胖Model拆成Model和ViewModel。

MVVM的关键是要有View Model!而不是ReactiveCocoa

ViewModel做什么事情?

就是把RawData变成直接能被View使用的对象的一种Model

不用ReactiveCocoa也能MVVM,用ReactiveCocoa能更好地体现MVVM的精髓。前面我举到的例子只是数据从API到View的方向,View的操作也会产生"数据",只不过这里的"数据"更多的是体现在表达用户的操作上,比如输入了什么内容,那么数据就是text、选择了哪个cell,那么数据就是indexPath。那么在数据从view走向API或者Controller的方向上,就是ReactiveCocoa发挥的地方。

我们知道,ViewModel本质上算是Model层(因为是胖Model里面分出来的一部分),所以View并不适合直接持有ViewModel,那么View一旦产生数据了怎么办?扔信号扔给ViewModel,用谁扔?ReactiveCocoa

在MVVM中使用ReactiveCocoa的第一个目的就是如上所说,View并不适合直接持有ViewModel。第二个目的就在于,ViewModel有可能并不是只服务于特定的一个View,使用更加松散的绑定关系能够降低ViewModel和View之间的耦合度。

那么在MVVM中,Controller扮演什么角色?

大部分国内外资料阐述MVVM的时候都是这样排布的:View <-> ViewModel <-> Model,造成了MVVM不需要Controller的错觉,现在似乎发展成业界开始出现MVVM是不需要Controller的。的声音了。其实MVVM是一定需要Controller的参与的,虽然MVVM在一定程度上弱化了Controller的存在感,并且给Controller做了减负瘦身(这也是MVVM的主要目的)。但是,这并不代表MVVM中不需要Controller,MMVC和MVVM他们之间的关系应该是这样:iOS 关于MVC 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,因为苹果本身并没有提供一个比较适合这种情况的绑定方法。iOS领域里KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。

在实际iOS应用架构中,MVVM应该出现在了大部分创业公司或者老牌公司新App的iOS应用架构图中,据我所知易宝支付旗下的某个iOS应用就整体采用了MVVM架构,他们抽出了一个Action层来装各种ViewModel,也是属于相对合理的结构。

所以Controller在MVVM中,一方面负责View和ViewModel之间的绑定,另一方面也负责常规的UI逻辑处理



你可能感兴趣的:(iOS高级进阶,iOS开发进阶)