原创:知识探索型文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的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
使用中等数量的样板代码强制执行严格的命名约定和类职责。
网友评论