另一则文章解释了iOS中的协调器

这个帖子是给谁的?

这篇文章是针对中级iOS开发人员的。 您应该熟悉UIKit框架,委托,面向对象的编程和Futures / Promises。 这篇文章不适合初学者。

什么是协调员?

协调器是一类,其职责是在应用程序中执行用户的操作。

这意味着什么?

假设您的应用程序有一个登录屏幕:

以下是描述典型登录的一系列事件:

  1. 用户填写电子邮件和密码文本字段
  2. 用户点击登录按钮

用户点击“登录”按钮后,可能会发生以下两种情况之一:

a)成功的登录事件

b)登录事件失败(电子邮件或密码无效/请求超时)

协调员负责执行成功的登录事件或失败的登录事件。

协调器如何帮助应用程序的体系结构?

首先,协调器模式显着减少了UIViewController文件中的代码行数。 它可以消除Massive View Controller综合症。 UIKit赋予了UIViewControllers如此强大的功能和责任,使用400多行代码创建UIViewController文件非常容易。

在每个iOS开发人员的职业生涯中,他/她都会在他/她创建或继承的代码库中遇到此问题。

根据个人经验,去年,当我被聘为Jr. Application Developer从事我的第一份专业工作时,我被立即负责创建应用程序。 使用标准的Model-View-Controller(唯一的一种控制器是UIViewController),快进了两个月,我创建了一个代码库,其中每个UIViewController文件的长度至少为600行或更多,而AppDelegate文件的长度为1300行( y!)

这可能发生在Jr. Developer的职业生涯中的某个时刻,这没关系。

协调器消除了Massive View Controller综合症,因为在代码库中使用它时会发生两件事:

  1. 协调器代替UIViewController承担导航的责任
  2. 协调器成为对象(协调器的委托)彼此交互的地方。 (这些代表进行诸如联网,将数据持久保存到磁盘,根据从API获取的数据创建特定于应用程序的数据模型等操作)。

这两件事的技术定义是:

  1. 它负责在其管理的UIViewController上进行导航方法调用
  2. 成为发生委托方法调用的中心

这是否违反了单一责任原则?

我认为事实并非如此。 为什么? 因为协调员执行用户的操作。 它的唯一职责是执行用户的操作。

这并不意味着它应该直接与API交互或将数据转换为类的特定于应用程序的实例(例如User类)或直接写入数据库。 它应该那些进程分别委派给其他对象,例如APIManager或UserService或RealmManager。

协调器直接管理导航,这意味着它在所管理的UIViewController上调用诸如present(viewController:)之类的方法。 另外,协调器还可以管理一系列子协调器(这与导航相关联,因为不同的UIViewController意味着不同的协调器)。

UIViewController会发生什么?

UIViewController发生了什么事情,因为它不再了解其他UIViewControllers(除非它具有子UIViewControllers,这是另一个主题)。 它不再担心导航,因为它被委派给其协调器。 它仅专注于管理其视图(监视用户输入,重新排列子视图等)。 它履行其作为视图控制器的角色。 最终结果是大大减少了UIViewController文件上的代码,这意味着更高的可读性。 后端逻辑与UIViewController分离,并移至协调器。

代码在哪里?

那么,协调器的基本实现是什么样的? 看起来像这样:

协调协议

这是一个LoginCoordinator实现的示例:

让我们逐行浏览此实现:

委托是LoginCoordinatorDelegate,不言自明。

init(delegate:navigationController) ,这里没有什么特别的事情,使用委托和它使用的navigationController创建一个登录协调器。

navigationController,它是Login View Controller的容器视图控制器。 与childCoordinator簿记和UIViewController解除/表示结合使用。

loginService ,代表负责查询Web API以获取用户信息的类。

start() ,这是创建和显示LoginVC的地方。 请注意, 调用super.start()可以确保如果多次调用start(),则应用程序将崩溃。

login(使用电子邮件:password :),当用户点击登录UIButton时,LoginVC会调用此方法。 请注意,这实际上是通过点击登录UIButton开始的过程的后端组件。 后端逻辑不包含在LoginVC中,而是包含在LoginCoordinator中。 还要注意,LoginCoordinator不会直接与Web API交互或直接发送网络请求。 它要求LoginService为此做这些事情。

LoginVC可能具有以下方法:

该代码很容易说明。 在将电子邮件和密码传递给LoginVC的代表LoginCoordinator之前,将对其进行验证。

符合LoginCoordinatorDelegate的AppCoordinator可能具有以下实现:

该代码也是不言自明的,因此我不会对其进行解释。

现在,让我们一起检查LoginVC loginButtonTapped()方法和LoginCoordinator login(with email:password)方法,以分析登录过程:

  1. 当用户点击登录按钮时,LoginVC会验证电子邮件和密码,并将这些字符串传递给其委托人(LoginCoordinator)
  2. LoginCoordinator 电子邮件和密码传递到其LoginService,然后LoginService创建URLRequest并将其发送到Web API,并将返回的数据转换为User实例。
  3. 然后,LoginCoordinator关闭LoginVC, 并将 User实例传递给其委托(AppCoordinator),以将其保存到磁盘,并将其自身释放,因为自登录过程最终完成以来,AppCoordinator现在将显示应用程序的其余部分
  4. AppCoordinator将User实例保存到磁盘,然后取消分配LoginCoordinator,最后创建一个TabCoordinator,它是应用程序的其余部分

请注意,LoginCoordinator如何成为LoginService,LoginVC和AppCoordinator之间的桥梁

通过将电子邮件和密码从LoginVC传递到LoginService,它充当了三个对象之间的中介。 LoginService创建了一个有效的User实例,LoginCoordinator将其传递给AppCoordinator。

这就是我之前说协调员执行流程时的意思。 LoginCoordinator组织了LoginVC,LoginService和AppCoordinator之间的交互,以创建和执行流程。

用户点击登录按钮->创建用户实例->保存用户实例并完成登录-> AppCoordinator显示应用程序的其余部分

结论

在我看来,协调员通过将后端逻辑与UIViewController分开来改善应用程序的体系结构,并减少了UIViewController的职责数量,从而提高了可读性。 尽管创建了更多的类,但是每个类在过程中都有各自的职责,这使得调试很多工作变得更加容易,因为过程中的每个部分都是隔离的,因此可以测试。

我希望您阅读此书后对协调员有更好的了解。 如果您想了解更多信息,请访问Sourosh Khanlou关于协调员的博客文章。 我在2017年使用Coordinators构建了四个应用程序,发现它确实提高了我的代码库的可读性,并清楚地分隔了每个功能。 如有任何疑问,请随时询问。

在我的Kio库中可以找到Coordinator协议和AbstractCoordinator的源代码。