当iPhone仅是第三部时,我在Apple Developer门户上有关iOS编程的第一篇教程的开头看到了此图: (仍然存在类似的文章,并且图表在那里:Cocoa核心能力。模型-视图-控制器) 该图展示了基本的iOS体系结构模式MVC 。 10年前,我以一种非常简单的方式理解了该图: UIView,UIScrollView或UITableView是该图上的视图 。 作为开发人员,我将它们安排在Interface Builder中的一个场景上,并将它们与我的源代码(在视图控制器中定义的出口和动作)绑定在一起。 最后一个正是MVC图中的控制器 。 我的应用程序将用户数据存储在例如文本文件中,或者在更复杂的情况下通过Core Data存储。 图表中的模型是允许访问此数据的类。 要添加的另一件事: 模型中没有业务逻辑代码,该模型不与视图通信。 视图控制器负责创建所有视图和模型,并在它们之间进行通信。 这样简单的系统的行为很明显:用户与视图进行交互,并且他的动作被传递给视图控制器。 最后一个执行计算,更改其自己的状态,并且此状态反映在视图中。 如果用户操作需要更改模型 ,则视图控制器会调用该模型进行更改。 如果模型发生更改,则会将该更改通知给视图控制器 。 视图控制器就是其中之一,它可以更新视图 。 这是对这种基本模式的简化甚至天真的理解。 但是它允许开发简单的应用程序,例如计算器或绘画工具。 我想展示一种开发和维护更复杂的应用程序的方法。 首先,让我们变换上面的图并以分层样式绘制它。 它使人想起大学时代熟悉的常见应用程序架构图: 该层是一个非常时髦的术语。 分层样式无处不在,包括应用程序体系结构。 我当时的所有项目都从该图开始,具有三个应用程序层:用户界面,业务逻辑和数据。 所有应用程序对象都属于这些层之一。 数据层和用户界面不进行通信,而是通过业务逻辑进行通信。 让我们复杂化该分层MVC图。 View-controller创建模型并在发生更改时调用它,并在图中显示为箭头。 箭头从视图控制器到视图 — 视图控制器创建所有视图 ,并在其状态或模型发生更改时对其进行更新。 该模型对视图控制器一无所知,如果模型发生更改,它会发布有关该视图的通知,或者更常见的是, 视图控制器会观察到模型更改。 它在运行时发生,我更喜欢使用虚线从模型到视图控制器绘制此箭头。 虚线箭头还应该显示从视图到视图控制器的连接 :用户在运行时与视图进行交互,但是视图不直接调用视图控制器 , 视图不知道视图控制器界面并通过Target-Action Design模式将用户操作传递给视图控制器 。 这是MVC的最简单或理想形式,适用于仅由一个视图控制器构造的小型应用程序。 让我们再添加一个view-controller 。 例如,单击视图控制器中的按钮(上面带有一个视图 […]
嗨伙计。 最近,MVVM已成为iOS应用程序的某种标准架构。 它提供了很好的关注点分离,格式化数据的好方法以及使用诸如RxSwift之类的框架的出色视图绑定机制。 在这篇文章中,我将提供一些技巧来简化该模式的实现。 可重用使视图变得简单 使用MVVM,视图与体系结构其余部分之间的分离非常清晰。 视图包括UIViewControllers及其出口。 实际上,实例化View变得越来越重要,特别是因为诸如Coordinator之类的模式越来越受欢迎。 在本文的其余部分中,我们将假定您正在实现这种体系结构。 Reusable是一种API,它带有对UIViews和UIViewControllers的便捷扩展,可以方便地以类型安全的方式实例化它们。 这是GitHub存储库:可重用。 它是与Carthage,CocoaPods和SPM兼容的轻量级API。 不使用它带来的幸福🖖真可惜。 基本上,Reusable提供了mixins(具有默认实现的协议),一旦您使它们符合适当的协议,它们就会向UIViews和UIViewControllers添加实例化函数。 在使用Coordinator模式时,有时需要实例化UIViewControllers并将其传递给ViewModels。 幸运的是,因为可重用在此方面有很大帮助。 这是将Reusable用于UIViewControllers实例化所需要做的事情: 为每个UIViewController创建一个Storyboard文件(当然,如果在同一个Storyboard中可能有多个UIViewController,但是为了简单起见,我们将仅考虑一个UIViewController) 将UIViewController设置为场景中的初始ViewController 创建一个UIViewController文件,其中ViewController类名与Storyboard文件名相同。 例如,如果故事板文件名为“ SettingsViewController.storyboard”,则UIViewController类将命名为“ SettingsViewController” 使UIViewController实现“ StoryboardBased”协议 就是这样。 现在,您可以使用单行代码实例化ViewController: 最酷的是, settingsViewController的类型是SettingsViewController ,不需要强制转换语句。 实际上,基于Storyboard的协议非常简单。 让我们深入了解一下: 基本上,它的作用是为实现该协议的每个UIViewController提供静态的“实例化”功能。 此函数返回UIViewController的实例。 由于“ Self”是函数的返回类型,因此类型推断可确保我们不必强制转换结果。 我强烈建议您深入研究可重用。 从类型安全的方式从Xib实例化UIView或使UITableViewCells出队时,这也将很有帮助。 面向协议的ViewModel 在当今的应用程序中,类似协调器的体系结构很常见,尤其是当与MVVM模式组合时。 这就是为什么我希望首先谈论Reusable的原因。 但是我发现有一个技巧非常有用,并且是可重用的补充。 它非常适合面向协议的方法中的MVVM模式。 这个想法不仅是为了简化UIViewControllers的实例化,而且是提供一种很好的方式来传递它们相关的ViewModels。 让我们写一个协议来定义拥有ViewModel的含义。 现在,我们可以将其与StoryboardBased混合使用,并提供一个静态函数,该函数以ViewModel作为参数实例化UIViewController。 条件扩展是一个非常强大的工具。 结合了“ StoryboardBased”和“ UIViewController”的“ where”语句使Self.instantiate函数可用,因此我们只需要将此调用包装在另一个设置UIViewController.viewModel属性的静态函数中即可。 假设我们有一个符合ViewModelBased协议的MyViewController: 使用ViewModel进行实例化将非常容易: 让我们进一步了解ViewModel抽象 到目前为止,我们仍然必须实例化ViewModel并将其提供给View。 […]
RxFlow是基于Reactive Flow Coordinator模式的iOS应用程序导航框架。 该项目是RxSwiftCommunity组织的一部分。 这三篇文章对它的详细概念进行了解释: RxFlow第1部分:理论上 RxFlow第2部分:实践中 RxFlow第3部分:提示和技巧 这是Github存储库:https://github.com/RxSwiftCommunity/RxFlow 感谢您的反馈,随时可以贡献contribute 我将介绍RxFlow :我的设计框架,在iOS应用程序中实现了Reactive Flow Coordinator。 RxFlow是RxSwiftCommunity支持的项目。 关于iOS应用程序中的导航,有两种选择: 使用Apple和Xcode提供的内置机制:Storyboard和Segues 直接在代码中实现自定义机制 这两种解决方案的缺点: 内置机制:导航是相对静态的,并且情节提要非常庞大。 导航代码污染了UIViewControllers 自定义机制:根据所选的设计模式(路由器,协调器),代码可能难以设置并且可能很复杂 RxFlow旨在: 促进将故事板切割成原子单元,以实现协作和UIViewControllers的可重用性 允许根据导航上下文以不同方式呈现UIViewController 简化依赖注入的实现 从UIViewControllers删除任何导航机制 促进反应式编程 在处理大多数导航案例的同时,以声明的方式表示导航 促进将应用程序切成逻辑导航块 从情节提要到协调器模式 随着我作为iOS开发人员(以及Android或Web应用程序开发人员)的经验的增长,我一直面临着有关导航的同样疑问。 对于所有其他概念问题,有很多模式可以解决常见的体系结构问题和关注点需求分离(MVC,MVP,MVVM,VIPER等)。 但是,一旦设计导航,我就被撕碎了: 如何在Storyboard / Segues中使用依赖项注入? 如何控制应用程序的流程? 如何摆脱UIViewControllers中的导航样板代码? 随着时间的流逝,我对iOS应用程序的构想从带有一个Storyboard的MVC到带有多个Storyboard的MVC,最终达到了我们可以称为当今最佳实践之一:带有Flow Coordinator的 MVVM。 这非常好,因为我们可以玩依赖注入,UIViewControllers可重用性和可测试性。 我有机会将这种模式应用于生产中的大型复杂应用程序。 但是最后,仍然有一些问题困扰着我: 我总是不得不一次又一次地编写协调器模式, 有很多委派模式用于允许ViewModel与协调器进行回通讯。 我开始研究Redux模式,尤其是导航状态机制。 我们可能有一个全局导航状态,该状态通过RxSwift Observables公开,并且有人在监听此状态并驱动导航。 我发现唯一令人不安的是这种导航状态的独特性以及它可能具有的不受控制的责任(以及它可以存储的海量数据) 导航只是一种状态的反射,这种状态可以逐步修改的想法开始出现。 一种状态,将散布在整个应用程序结构中,而不是存储在单个位置中,而是由观察者统一起来,可以对它作出反应并因此驱动导航。 在本文的后面,这些散布在应用程序中的小状态称为“ 步骤” […]
在本教程的第一部分中,我总体上讨论了协调器的方法,并展示了一些与实现有关的常见示例。 为了与本文保持一致,请阅读上一部分。 在这一部分中,我想介绍一些使用协调器的极端情况。 我想最有趣的部分是: AppDelegate配置 管理启动选项 深度链接和协调员推送通知处理 我将逐步说明解决方案并进行解释。 如何使用主应用程序协调器配置AppDelegate? 由于所有导航逻辑都移至AppCoordinator,因此AppDelegate变得非常简单。 因此,您需要做的是创建一个协调器,注入rootController并调用start()。 我们希望通过展示一个教程,展示一个身份验证流程,向他们介绍新功能或仅显示主屏幕来向用户介绍我们的应用程序。 我们应该谨慎处理这种行为。 假设我们有3种不同的情况: 用户应查看入门教程(我们将显示入门屏幕) 用户应登录(我们显示登录屏幕) 用户已完成之前的两个步骤,仅看到主屏幕 为了轻松处理所有这些情况,我们创建了一个枚举作为协调者的助手。 该枚举应检查所有标志,并返回协调器应遵循的正确方案。 我将其命名为实体讲师,因为它指示协调员接下来要做什么。 怎么处理呢? 正如您在上一部分中所记得的,我告诉您有关BaseCoordinator的信息 ,其中包含子协调器数组。 所有协调员都继承它。 这意味着我们可以循环所有孩子并执行动作。 为此,我们只需添加一种方法即可处理DeepLink逻辑本身,也可以循环处理子代以找到可以处理它的方法。 它将像一棵树。 我们可以创建特定的协议来实现此目标。 让我们更新协调器协议: 现在,我们将两个带有空主体的方法添加到BaseCoordinator中,以使其保持可选状态。 孩子们可以继承这些方法之一,也可以两种都继承。 在某些情况下,可以使用不带选项的start来运行默认行为,但是如果继续进行深层链接方案,则应添加有关演示案例的信息。 如何实现呢? 更好的方法是在项目中添加一些实体,其中包含所有深层链接快捷方式,并创建可以使用start()方法发送的对象。 你想念枚举吗? 让我们添加一个新的! 它将是DeepLinkOption: 好处是,协调器中所有的DeepLink方法都将像切换为枚举一样。 是的,与上一个示例中的Instructor相同,您是正确的。 我们可以根据需要添加一些其他的build方法(带有…): 在此迭代之后,如果我们返回AppDelegate并对其进行一些更新,它将看起来像这样: 好了,看起来不错吗?🤔然后您将收到一个推送通知或深层链接,您只需构建您的DeepLink并通过AppCoordinator进行此操作即可。 结论 在我们尝试在代码中实现的每个新解决方案中,我们都面临着很多极端的情况,并且还面临着一些不太漂亮的解决方案。 它不应该像炒作那样驱动开发,我们只需要逐步改进所有棘手的部分即可。 如果您有任何疑问或新的特定问题,请随时给我写信。 并检查整个实现的Github回购。
RxFlow是基于Reactive Flow Coordinator模式的iOS应用程序导航框架。 该项目是RxSwiftCommunity组织的一部分。 这三篇文章对它的详细概念进行了解释: RxFlow第1部分:理论上 RxFlow第2部分:实践中 RxFlow第3部分:提示和技巧 这是Github存储库:https://github.com/RxSwiftCommunity/RxFlow 感谢您的反馈,随时可以贡献contribute 让我们深入探讨我在响应式编程方面遇到的一些技巧和窍门。 UIViewControllers使反应 正如我们在第2部分中所看到的,我们需要在某个时候以响应方式知道何时显示一个Presentable 。 一个可呈现对象公开了3个可观察对象: 在RxFlow中 ,UIViewController符合此协议,因此我们必须找到一种使它们具有反应性的方法。 希望在此过程中发现的一个很棒的项目在此方面起到了很大的帮助:RxViewController。 通过应用我在这篇文章中描述的模式,它为UIViewControllers提供了Reactive扩展:Swift中的Verstatile命名空间。 此外,它使用RxCocoa内置函数可以观察选择器调用。 一旦理解了这一概念,便对UIViewController进行了自己的扩展。 作为记录,这就是协调器的用法,其中“ nextPresentable”是由Flow上的“ navigation (to 🙂 ”函数生成的Presentable 。 在关联的Presentable第一次显示之后,我们仅听下一个Stepper 。 让我们暂停一下 RxFlow中的另一个关键原理是: 流中发生的事情,留在流中 。 因此,如果Flow不再位于视图层次结构的顶部,我必须找到一种方法来“暂停” Steps的订阅。 RxSwift不提供“开箱即用”的方式来暂停订阅,但RxSwiftExt可以。 这是来自RxSwiftCommunity的项目。 它为RxSwift添加了许多新的运算符,例如“ pausable”。 除非第二个可观察序列中的最新元素为true,否则它将暂停源可观察序列的元素。 让我们看一下实现。 实际上,这只是3个RxSwift内置运算符的组合: withLatestFrom:与由主要Observable触发的值相关联,该值是另一个称为“ pauser”的Observable的最后一个值(驱动暂停的那个值) 过滤器:仅接受“ pauser”中可观察到的值为true的值 映射:忽略制表符的Observable值,以便仅返回的值是主Observable的值 再次,这是协调器使用的方式: 这很容易理解:当“ rxVisible”的Observable值为false时,nextStepper的步骤将暂停。 具有存储属性的协议? 作为面向协议的框架, RxFlow希望开发人员实现多种协议。 当您建立这种框架时,您不希望用户为实现那些协议而必须实现的过多功能或特性感到困扰。 […]
您是否曾经遇到过这样的情况,即您的viewController变得如此紧密并相互依赖。 您的导航分散在您的所有代码中。 您可能还听说过Massive视图控制器问题。 这与以下事实有关:MVC模式的视图控制器通常会做过多的工作,包括视图设置代码本身。 以某种方式使视图控制器实际上变成一个视图(还有更多…) 视图控制器不应该执行的任务之一。 屏幕导航管理和应用程序流程。 什么是协调器模式? 由Soroush Khanlou在2015年NSSpain会议上介绍给iOS社区。Coordinator模式提供了导航逻辑的封装。 换句话说:而不是从其他视图控制器推送和呈现ViewController。 所有屏幕导航将由协调员管理。 因此,视图控制器将被隔离并且彼此不可见 ,并且可以轻松地重用 。 如上图所示。 协调器模式可以通过以下方式描述: 我们可能有一个协调员一个或多个视图控制器。 每个协调器都使用通常称为“ start ”的方法显示其viewController。 每个viewController都有一个对其协调器的委托引用。 每个协调员都有一系列子协调员。 每个子协调器都有对其父级的委托引用。 让我们继续练习。 重要提示:您可能会发现以下示例与其他实现略有不同。 这就是我个人使用它的方式。 但是主要机制在任何地方都是相同的。 在这里,我们将有两个协调器管理三个视图控制器,以表明一个协调器可以具有一个或多个视图。 快速创建一个新的单视图项目。 具有三个视图控制器:FirstViewController,SecondViewController和ThirdViewController。 在每个视图控制器上,添加一个按钮以导航到以下视图控制器。 首先,我们将创建一个协调器协议。 通过一个子协调器数组和一个初始化方法,该方法接收导航控制器作为参数。 然后是第一个协调器,它将管理第一个视图控制器。 使用start方法实现,将第一个视图控制器添加到导航控制器中。 firstCoordinator有两个扩展,一个用于导航到下一个viewController。 第二个是导航回第一个协调器。 我们需要保持子协调器数组与当前协调器堆栈更新。 然后,不要直接在didfinishlaunchingwithoptions方法中创建主控制器。 我们使用主navigationController作为参数创建了第一个协调器。 并且start方法将负责显示第一个viewController。 现在为了导航到下一个viewController。 我们将不得不致电协调员。 由FirstViewControllerDelegate表示。 正如先前所说。 协调者可以管理一个或多个viewController。 因此,在这里,secondCoordinator将同时处理第二个和第三个viewControllers。 首先,我们创建一个自定义的后退按钮,调用一个协调器方法navigationToFirstpage : 重要说明 :在协调器之间切换时。 如果未覆盖操作,则默认的导航控制器后退按钮将中断协调器逻辑 。 我们应该绝对使用协调器方法调用自己的后退操作,以确保子协调器数组得到正确更新 […]
当视图控制器必须决定下一个屏幕要推送或显示的内容时,协调器(有时称为流管理器)是对常见问题的解决方案。 为了更清楚地了解这个常见问题,我们知道: UIViewControllers不应显示其他UIViewControllers。 视图控制器应该唯一的职责是呈现数据和捕获事件。 应该有一个单独的组件负责处理演示视图。 它负责流程逻辑,并从视图控制器中删除该职责 换句话说,如果您在视图控制器中的某处有这段代码(或类似的代码),则可能需要考虑使用此模式。 self.navigationController?.pushViewController(someViewController,动画:true) 当视图控制器本身决定将下一个视图控制器推入 self.navigationController 时,视图控制器将紧密耦合 。 使用这种方法,代码库将很难更改和维护,并且视图控制器几乎无法重用。 协调员可以轻松解决此问题 协调器负责管理一组视图控制器,它将负责流程逻辑(流程是一组具有类似用途(例如注册)的屏幕。 它处理导航流程,并负责创建和配置视图控制器。 使用协调器的主要优点是它可以帮助我们从视图控制器中消除这种责任。 这是处理UIViewControllers呈现的更优雅,更简洁的方法。 协调器负责创建导航控制器和任何子视图控制器。 然后,视图控制器是完全独立的,并且不了解使用它们的上下文,从而改善了可重用性和测试。 给我看一些代码 协调人协议: 所有协调员必须遵守协议: 协议协调员:类{ func start() } 这使我们可以将协调器的初始化与开始工作分开。 它可以帮助我们根据需要创建它,并且只有在准备就绪时才能启动它。 公共类AuthCoordinator:协调器{ 私人让navigationController:UINavigationController 公共init(navigationController:UINavigationController){ self.navigationController = navigationController } public func start(){ 如果登录{ showDashboard() }其他{ showAuthentication() } }私人功能showDashboard(){ 让dashboardViewController = DashboardViewController() dashboardViewController.delegate = self self.navigationController.setViewControllers([dashboardViewController],动画:true) }私人功能showAuthentication(){ 让loginViewController = […]
2015年,在著名的iOS会议NSSpain’15上,Soroush Khanlou作了介绍性演讲“ Presenting Coordinators”。 在这次演讲中,他描述了协调员的整个想法,并展示了一些用Objective-C编写的示例。 总体思想来自《企业应用程序体系结构模式》一书,该书解释了应用程序控制器模式,并被Soroush采纳用于移动开发。 您可以在此处查看演讲视频。 我一年前喜欢这个视频,整个想法给我留下了深刻的印象。 在二月的一个寒冷的夜晚,我用这种架构方法的第一次迭代编写了一个示例项目。 当然,我使用Swift作为主要语言。 之后,我一步一步改进了这种方法,并涵盖了越来越多的用例。 两个月后,我开始将协调器集成到生产应用程序中。 最初,协调员只驱动了少数功能,但最后,应用程序的框架却完全由它们驱动。 后来,我添加了深层链接支持,推送通知,强制触摸功能以及灵活的流程,所有这些都由协调员处理。 我现在想与您分享的是这种经历。 如果您想跳过我的解释并查看代码,请访问以下链接。 让我们从一堆问题开始。 什么是移动应用程序中的流程? 流是逻辑上链接的屏幕队列。 我们所有的屏幕都可以按流程划分:身份验证流程,电话验证流程,预订流程,个人资料编辑流程等。 我们通常如何管理流中的屏幕? 假设我们有一个身份验证流程,并且在流程中我们需要验证用户的电话。 让我们以这样的方案为例: 我们通常如何处理此流程中的导航? 在最常见的情况下,控制器告诉路由器推送新的控制器。 它在代码中的外观如下: 下一个常见情况是在控制器之间发送数据。 想象一下,我们有一堆控制器,我们需要在它们之间共享数据。 我们如何做到这一点? 使流独立的另一个常见原因是它们可以在不同地方重用的能力。 例如,假设您有一个电话验证流程,然后成功将其用作身份验证流程的一部分。 现在,如果您需要在配置文件中使用相同的流程,则可以。 引言摘要 直接处理流程的方法通常非常糟糕: 控制器很难重用 每个控制器都知道其他控制器 很难改变流量 很难测试 协调员 模组 首先,让我们介绍一下模块。 模块是MVC,MVP,MVVM和Viper架构方法的一种架构元素。 在最简单的情况下,对于MVC,模块是控制器,对于Viper,模块是Interactor-Presenter-View。 我们需要做的是编排模块。 什么是协调员? 协调器是一个对象,该对象处理导航流并在打开下一个链后共享下一个协调器的流处理。 这意味着协调员应仅在屏幕之间保持导航逻辑。 协调器可以保留对存储的引用,该存储包含工厂用于创建模块的数据,但是它们永远不能处理模块的业务逻辑,也不能驱动单元的行为。 只有在点击一个单元格后按下下一个屏幕时,才发生单元格交互。 我们为什么要使用它? 主要目标是承担模块之间的未链接责任,并彼此完全独立地构建模块。 迭代之后,我们可以轻松地以不同的流程重用它们。 回到前面的示例,让我们看一下如何改进身份验证流程。 首先,我们需要分离两个不同的流程:身份验证和电话验证。 拆分后,我们可以在所需的任何地方重复使用它们。 […]
RxFlow是基于Reactive Flow Coordinator模式的iOS应用程序导航框架。 该项目是RxSwiftCommunity组织的一部分。 这三篇文章对它的详细概念进行了解释: RxFlow第1部分:理论上 RxFlow第2部分:实践中 RxFlow第3部分:提示和技巧 这是Github存储库:https://github.com/RxSwiftCommunity/RxFlow 感谢您的反馈,随时可以贡献contribute 综上所述, RxFlow旨在: 简化将导航切割为逻辑部分 从视图控制器中删除导航代码 鼓励视图控制器的可重用性 促进反应式编程 促进依赖注入 快速提醒您以下术语: Flow :每个Flow都定义了应用程序中的导航区域。 步骤 :每个步骤都是应用程序中的导航状态。 流程和步骤的组合描述了所有可能的导航操作。 步进器 :可以是任何可以发出步进的东西。 步进器将负责触发流中的每个导航动作 可表示的 :它是可以表示的东西的抽象,基本上UIViewController和Flow是可表示的 NextFlowItem :它告诉协调器将在其响应式机制中产生新步骤的下一件事是什么 协调员 : 协调员的工作是以一致的方式混合流程和步骤的组合 同样重要的是要记住, RxFlow使用面向协议的编程,这样它才不会将代码冻结在继承层次结构中。 在RxFlow仓库中,您将找到一个演示应用程序。 它几乎显示了每种可能的导航类型: 导航堆栈 标签栏 掌握/细节 模态弹出 RxFlow主要是关于以反应方式处理导航状态更改。 为了在多个上下文中重用,这些状态必须不知道用户所处的当前导航流。因此,状态不是表示“我要转到此屏幕”,而是表示“某人或某件事已完成”。此操作”, RxFlow将根据当前导航流选择正确的屏幕。 使用RxFlow时 ,此导航状态称为步骤 。 枚举是描述步骤的好方法: 它们易于使用, 一个值只能定义一次(因此状态是唯一的) 使用它们是安全的,因为Swift希望您在switch语句中实现所有可能的值 他们可以嵌入将从一个屏幕提供给另一个屏幕的值 它们是值类型,因此不存在传播不受控制的共享引用 例如,在演示应用程序中,所有这些都是我们涵盖导航可能性所需的所有步骤 。 […]
通过查看此架构,我们看到协调器需要实例化,添加和删除其他协调器,实例化控制器,并知道如何在应用程序中导航。 没有一种方法可以实现这种逻辑。 如您所见,我的方法依赖于Andrey Panov的方法。 为了实例化协调器,我们使用CoordinatorFactory。 在BaseCoordinator中,我们具有添加和删除协调器的逻辑。 ChildCoordinators数组存储活动的协调器。 我们需要对它们有充分的参考,否则,它们将从内存中删除。 查看应用架构。 如果用户使用Profile VC,则Profile协调器位于Main协调器的childCoordinators变量中。 同时,主协调器位于应用程序协调器的childCoordinators变量中。 如果我们从Profile VC导航回A VC,则Main协调器将从childCoordinators数组中删除Profile协调器,我们将不再有强大的参考资料。 为了实例化视图控制器,我们使用ViewControllerFactory。 这个课很简单。 我们使用工厂模式来创建控制器。 对于路由,我们使用一个Router对象。 它具有对导航控制器的引用,因此路由器可以为我们显示,推动,关闭和弹出控制器。 它还支持自定义过渡。 现在,我们的协调器对象具有所需的所有条件,让我们尝试使用它。 实施协调员 在AppDelegate中,我们将初始化Application协调器并设置根视图控制器。 应用程序协调器将决定我们应该使用LaunchInstructor对象来进行认证还是主流。 因为这只是概念证明,所以我们不会实现它。 但是,其想法是LaunchInstructor应该检查auth令牌是否可用,如果可用,则注册完成。 启动应用程序时,我们可以登录或注册。 完成后,登录过程Application协调器将删除Auth并启动Main协调器。 到目前为止我们得到了什么? 控制器中的代码更少,因为导航逻辑已失效。 控制器不了解其他控制器。 可重用性 正如您在模式中看到的,我们在两个地方都有更改密码协调器。 如果要重用任何流,则需要创建一个选定协调器的新实例,一切准备就绪。 流量变化 产品经理来找你多少次,说一个小小的改变。 我们只需要添加演练和深层链接。 如果问我太多次。 幸运的是,现在这种过渡将不再那么痛苦。 如果要添加演练,则需要创建一个新的协调器并更改LaunchInstructor对象。 我们不需要更改应用程序委托或任何视图控制器中的任何内容。 向项目添加深层链接和推送通知可能非常痛苦。 但是,流量协调器也有解决方案。 启动协调器时,将使用startWithOption并创建新流程或重复使用现有流程。 测试中 现在,我们的控制器和视图模型更加整洁,可重用,并且没有太多依赖项。 因此对我们来说编写测试更容易。 在本文中,我们将不涉及测试,因为这可能是一个全新的话题。 结论 使用流程协调器,我们从视图控制器中删除了导航逻辑。 我们的代码更干净,可重复使用,更易于更改且更易于测试。 起初,它可能会发现有太多的代码要编写。 但是,您可以编写许多代码-BaseCoordinator,Router,LaunchInstructor,您可以在其他项目中重用,因此这是第一次,需要进行大量工作。 有人说这太复杂了,我不这么认为。 […]