原创:知识探索型文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 一、简介
- 二、VIP Cycle
- 三、总结
- 参考资料
一、简介
iOS同学一定了解或使用过一些常用的iOS页面架构模式,比如MVC、MVVM、MVP,甚至是VIPER。当MVC、MVVM、MVP对于某些复杂页面不够用、而你又讨厌VIPER时,不妨试试Clean Swift(VIP)这种架构。本文将对此架构的原理和实践方式做一个详细的说明以帮助感兴趣的同学快速入门。
Clean Swift(也称作VIP) 最初是由 Raymond Law 在他的网站 clean-swift.com 上提出的。 其背后思想是在遵循 Uncle Bob 的Clean Architecture中的主要思想的同时,解决庞大视图控制器问题。
在使用Clean Swift模式时,我们可以将页面或页面上的某一模块看作一个场景。理论上,每个场景由大约6个组件构成:
-
View Controller(视图控制器,包括xib或storyboard) -
Interactor(交互器) -
Presenter(展示器) Model-
Router(路由器。可选) -
Worker(工作器,可以看作helper。可选)
其中,视图控制器(V)、交互器(I)和展示器(P)是 Clean Swift 的三个主要组件。 它们作为彼此的输入和输出,如下图所示:
视图控制器的输出连接到交互器的输入,交互器的输出连接到展示器的输入,展示器的输出连接到视图控制器的输入。 这意味着控制流和数据流始终是单向的。这被称为 VIP Cycle。
二、VIP Cycle
Clean Swift 架构使用VIP Cycle来帮助你分离代码逻辑。VIP Cycle由ViewController、Interactor和 Presenter组成。ViewController 负责显示,Interactor 负责业务逻辑,Presenter 负责展示逻辑。
ViewController(视图控制器)
ViewController是在 VIP Cycle 中第一个触发动作的类。它的作用如下:
- 定义一个场景并包含一个或多个视图。
- 持有
Interactor和Router的实例。 - 将视图中的动作封装成一个
Request请求传递给Interactor(输出),并将Presenter触发的动作作为ViewController的输入。
Interactor(交互器)
包含该场景所有的业务逻辑(这对编写单元测试好处极大,因为测试 Interactor时,该场景中所有的业务逻辑都经过了测试)。
- 持有
Presenter的实例。 - 根据输入(来自
ViewController的Request),指挥Worker进行操作(比如从数据库、网络获取数据)。完成操作时,将从Worker处获取到的原始数据封装成Response传递给Presenter。
注意:Interactor 不需要也不应该导入UIKit。
Presenter(展示器)
接收到 Interactor 传递的 Response 后,Presenter 将原始数据转换成用于显示的 viewModel,然后将 viewModel 传递回 ViewController 以显示给用户。
保存对 ViewController(输出)的弱引用。
Worker(工作器)
当所有的业务逻辑都位于 Interactor 中时,可能会导致Interactor是一个非常大的类。 为了防止这种情况,一个Interactor 可以使用多个 Worker。 Worker 是 Interactor 的助手,可以帮助接收数据。
-
Worker是处理不同底层操作的抽象,比如从网络/数据库获取信息、上传/下载照片、喜欢/关注用户等。 - 应遵循单一职责原则(一个
Interactor可能包含许多具有不同职责的Worker)。 -
Worker必须是通用的,这样就可以被多个Interactor使用。
注:如果你使用第三方SDK,比如使用 AFNetworking 做网络请求,而网络请求是在Worker里面做的,那么只需在 Worker 中引入AFNetworking。
Router(路由器)
有可能存在当前场景的 ViewController 将展示另一个 ViewController 的情况。 在 Clean Swift中,ViewController 之间的导航是由 Router 完成的。
当屏幕或场景发生转换时,ViewController 需要向Interactor发起Request,然后 Interactor 需要向Presenter 进行询问,最终由 Presenter 来决定 ViewController 可以使用 Router 路由到哪一个 ViewController。
-
Router从ViewController中提取所有的导航逻辑,这使得ViewController具有哪些导航选项变得一目了然。 - 保存对源
ViewController的弱引用。
Model
在 VIP Cycle 中,每个类在向该循环中的其他类进行请求动作时都会创建一个数据对象。 这样做的目的是解耦各个类。
- 当
ViewController向Interactor请求一个动作时,ViewController将添加一个“请求”对象(Request)。 该对象包含Interactor在执行业务逻辑时需要的所有数据。 -
Interactor将处理来自ViewController的请求。 处理完成后,它将向Presenter返回一个“响应”对象(Response)。 -
Presenter将解析来自Interactor的 原始数据,提取/转换用于显示的数据并封装为 “ViewModel”对象,该对象将被发送到ViewController。 - 当
ViewController接收到ViewModel时,ViewController只需要使用ViewModel中的数据更新 UI即可。
三、总结
完整模式
ViewController 在初始化完成后,在内部创建 Interactor、Presenter、Router实例,ViewController仅保存Interactor 和 Router 实例,将 Presenter 实例传递给 Interactor 来保存,并将ViewController作为弱引用传递给 Presenter 和 Router(防止循环引用)。
优点
- 易于维护、扩展和
bug fix。因为你可以确切地知道哪个逻辑位于哪个类中。 - 很好地执行了单一职责原则。
- 很好地使用
Worker构建可重用的组件。 - 由于使用协议来进行类之间的解耦,因此当需要替换一个类时,只需要让新的类遵从某个协议,而无需修改其他类的代码。
- 方便进行单元测试,并容易达到很高的代码覆盖率。
缺点
- 许多协议的命名和职责复杂,起初可能会混淆协议在哪里定义。
- 很难保持
ViewController和Presenter之间的完全分离。因为有时Presenter只是调用ViewController的方法而不是准备UI显示用的数据,因此它看起来没用,只是为了要遵守样板代码而不得不这样做。
总结
-
Clean Swift不是最容易维护的,但可能是避免耦合并能够保持高代码覆盖率的最佳方法。 -
VIP Cycle使用中等数量的样板代码强制执行严格的命名约定和类职责。











网友评论