IOS架构总结

来源:互联网 发布:淘宝试用中心成功秘诀 编辑:程序博客网 时间:2024/05/16 23:52

1.MVC For Cocoa
Cocoa的MVC模式驱使人们写出臃肿的视图控制器,因为它们经常被混杂到View的生命周期中,因此很难说View和ViewController是分离的。尽管仍可以将业务逻辑和数据转换到Model,但是大多数情况下当需要为View减负的时候我们却无能为力了,View的最大的任务就是向Controller传递用户动作事件。ViewController最终会承担一切代理和数据源的职责,还负责一些分发和取消网络请求以及一些其他的任务,因此它的名字的由来…你懂的。

这里写图片描述
你可能会看见过很多次这样的代码:

var userCell = tableView.dequeueReusableCellWithIdentifier("identifier") as UserCelluserCell.configureWithUser(user)

这个cell,正是由View直接来调用Model,所以事实上MVC的原则已经违背了,但是这种情况是一直发生的甚至于人们不觉得这里有哪些不对。如果严格遵守MVC的话,你会把对cell的设置放在 Controller 中,不向View传递一个Model对象,这样就会大大增加Controller的体积。

“Cocoa 的MVC被写成Massive View Controller 是不无道理的。”
直到进行单元测试的时候才会发现问题越来越明显。因为你的ViewController和View是紧密耦合的,对它们进行测试就显得很艰难–你得有足够的创造性来模拟View和它们的生命周期,在以这样的方式来写View Controller的同时,业务逻辑的代码也逐渐被分散到View的布局代码中去。

“View和Controller的接口并不适合单元测试。”

2.MVP (MVP 实现了Cocoa的MVC的愿景)

这里写图片描述

这看起来不正是苹果所提出的MVC方案吗?确实是的,这种模式的名字叫做MVC,但是,这就是说苹果的MVC实际上就是MVP了?不,并不是这样的。如果你仔细回忆一下,View是和Controller紧密耦合的,但是MVP的协调器Presenter并没有对ViewController的生命周期做任何改变,因此View可以很容易的被模拟出来。在Presenter中根本没有和布局有关的代码,但是它却负责更新View的数据和状态。

MVP是第一个如何协调整合三个实际上分离的层次的架构模式,既然我们不希望View涉及到Model,那么在显示的View Controller(其实就是View)中处理这种协调的逻辑就是不正确的,因此我们需要在其他地方来做这些事情。例如,我们可以做基于整个App范围内的路由服务,由它来负责执行协调任务,以及View到View的展示。这个出现并且必须处理的问题不仅仅是在MVP模式中,同时也存在于以下集中方案中。

3.MVVM – 最新且是最伟大的MV(X)系列的一员

MVVM架构是MV(X)系列最新的一员,因此让我们希望它已经考虑到MV(X)系列中之前已经出现的问题。
从理论层面来讲MVVM看起来不错,我们已经非常熟悉View和Model,以及Meditor,在MVVM中它是View Model。

这里写图片描述

它和MVP模式看起来非常像:

  • 1.MVVM将ViewController视作View
  • 2.在View和Model之间没有紧密的联系
  • 此外,它还有像监管版本的MVP那样的绑定功能,但这个绑定不是在View和Model之间而是在View和ViewModel之间。
    那么问题来了,在iOS中ViewModel实际上代表什么?它基本上就是UIKit下的每个控件以及控件的状态。ViewModel调用会改变Model同时会将Model的改变更新到自身并且因为我们绑定了View和ViewModel,第一步就是相应的更新状态。

    绑定

    我在MVP部分已经提到这点了,但是该部分我们仍会继续讨论。
    如果我们自己不想自己实现,那么我们有两种选择:

  • 基于KVO的绑定库如 RZDataBinding 和 SwiftBond
  • 完全的函数响应式编程,比如像ReactiveCocoa、RxSwift或者 PromiseKit

  • 事实上,尤其是最近,你听到MVVM就会想到ReactiveCoca,反之亦然。尽管通过简单的绑定来使用MVVM是可实现的,但是ReactiveCocoa却能更好的发挥MVVM的特点。
    但是关于这个框架有一个不得不说的事实:强大的能力来自于巨大的责任。当你开始使用Reactive的时候有很大的可能就会把事情搞砸。换句话来说就是,如果发现了一些错误,调试出这个bug可能会花费大量的时间.


    让我们再来看看关于三个特性的评估:

        *任务均摊* -- 在例子中并不是很清晰,但是事实上,MVVM的View要比MVP中的View承担的责任多。因为前者通过ViewModel的设置绑定来更新状态,而后者只监听Presenter的事件但并不会对自己有什么更新。    *可测试性* -- ViewModel不知道关于View的任何事情,这允许我们可以轻易的测试ViewModel。同时View也可以被测试,但是由于属于UIKit的范畴,对他们的测试通常会被忽略。    *易用性* -- 在我们例子中的代码量和MVP的差不多,但是在实际开发中,我们必须把View中的事件指向Presenter并且手动的来更新View,如果使用绑定的话,MVVM代码量将会小的多。

    “MVVM很诱人,因为它集合了上述方法的优点,并且由于在View层的绑定,它并不需要其他附加的代码来更新View,尽管这样,可测试性依然很强。”

    4.VIPER–把LEGO建筑经验迁移到iOS app的设计

    VIPER是我们最后要介绍的,由于不是来自于MV(X)系列,它具备一定的趣味性。
    迄今为止,划分责任的粒度是很好的选择。VIPER在责任划分层面进行了迭代,VIPER分为五个层次:

    VIPER
    VIPER

    交互器 – 包括关于数据和网络请求的业务逻辑,例如创建一个实体(数据),或者从服务器中获取一些数据。为了实现这些功能,需要使用服务、管理器,但是他们并不被认为是VIPER架构内的模块,而是外部依赖。

        展示器 -- 包含UI层面的业务逻辑以及在交互器层面的方法调用。    实体 -- 普通的数据对象,不属于数据访问层次,因为数据访问属于交互器的职责。    路由器 -- 用来连接VIPER的各个模块。

    基本上,VIPER模块可以是一个屏幕或者用户使用应用的整个过程–想想认证过程,可以由一屏完成或者需要几步才能完成,你的模块期望是多大的,这取决于你。

        Model 逻辑通过把实体作为最小的数据结构转换到交互器中。    Controller/Presenter/ViewModel的UI展示方面的职责移到了Presenter中,但是并没有数据转换相关的操作。    VIPER是第一个通过路由器实现明确的地址导航模式。

    “找到一个适合的方法来实现路由对于iOS应用是一个挑战,MV(X)系列避开了这个问题。”

    1 0
    原创粉丝点击