RxFlow第2部分:实践中

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语句中实现所有可能的值
  • 他们可以嵌入将从一个屏幕提供给另一个屏幕的值
  • 它们是值类型,因此不存在传播不受控制的共享引用

例如,在演示应用程序中,所有这些都是我们涵盖导航可能性所需的所有步骤

使用RxFlow ,所有导航代码(例如呈现或推送视图控制器)都在Flows中声明。 Flow表示应用程序中的逻辑导航部分,当与特定的Step组合时,它将触发一些导航动作。

为此, 流程必须实现:

  • 一个“ navigation (to 🙂 ”功能,使导航动作根据流程和步骤进行
  • 一个“ ” UIViewController,它将基于此Flow中的导航

这是一个处理UINavigationController及其导航堆栈的Flow示例。 在此流程中 ,可以执行三个导航操作。

当我们学习函数式反应式编程时,我们经常会读到副作用 。 FRP的目的是传播事件并在整个过程中应用它们的功能。 这些功能可能会改变这些事件,并最终(但不是必须)执行将执行您想要的任何功能的代码(进行一些联网,保存文件,显示警报等):这些都是副作用

由于RxFlow依赖于反应式编程,因此我们可以轻松地识别固有的概念:

  • 事件 :这些是发出的步骤
  • 函数 :这是“ navigation(to 🙂 ”函数
  • 转换 :“ navigation (to 🙂 ”功能将** Step **转换为NextFlowItem
  • 副作用 :这些是在“ navigation (to 🙂 ”中执行的导航操作(例如,函数“ navigationToMovieListScreen () ”将新的UIViewController推入导航堆栈)

基本上, NextFlowItem是一个简单的数据结构,其中包含PresentableStepper

Presentable会告诉协调员您将要呈现的下一件事,而Stepper会告诉协调员接下来将要发出Steps的事物。

默认情况下,所有类型的UIViewControllers都是Presentable也是可表示的,因为有时您将要启动一个在其自己的Flow中描述的全新导航区域,因此RxFlow认为它可以呈现。

协调员为什么要了解Presentables

可表示性是可以表示的事物的抽象。 因为除非显示其关联的Presentable ,否则无法发射StepPresentable提供协调者将订阅的Reactive可观察对象(因此它将知道Presentable的呈现状态)。 因此,在尚未完全显示其可演示对象时,没有引发步骤的风险。

Stepper可以是任何东西:自定义UIViewController,ViewModel,Presenter…在协调器中注册后, Stepper可以通过其“ step ”属性(RxSwift主题)发出Steps协调员将监听这些步骤,并调用流程的navigation(to 🙂 ”功能。

这是演示应用程序中Stepper的示例。

在此示例中,当用户在列表中选择电影时,将调用选择功能。 该函数在“ self.step” Rx流中发出一个新值。

总结一下导航过程:

  • 导航(to 🙂函数以Step作为参数调用
  • 根据此步骤 ,称为一些导航代码( 副作用
  • 同样根据该步骤 ,产生NextFlowItems 。 因此, PresentablesStepper已注册到协调器中
  • 步进器发出新的步进 ,在这里我们再次走

因为什么也不允许应用程序一次具有多个导航。 例如,选项卡栏的每个项目都可以引至导航堆栈。 触发显示UITabbarController的步骤将在每个导航堆栈中生成NextFlowItem

您可以查看演示应用程序以了解其概念。 这是我们将UITabBarController与2个流连接的摘录(每个描述与选项卡栏项关联的导航堆栈):

静态函数“ Flows.whenReady() ”将启动Flows ,并在准备好显示这些Flows时(即,在选择该Flow的第一个屏幕时)调用该Closure。

因为导航流程必须结束! 例如,导航堆栈的最后一个屏幕将不允许进一步的导航,而仅允许UINavigationController自身处理的后退操作。 在这种情况下, navigation (to 🙂函数将返回NextFlowItem.noNavigation

正如我们已经看到的,有可能同时浏览多个Flow 。 例如,导航堆栈中的屏幕可以启动弹出窗口,该弹出窗口也可以包含另一个导航堆栈。 从UIKit的角度来看,UIViewController层次结构非常重要,我们不能与Coordinator内部的层次结构搞混。

这就是为什么当当前未显示Flow时(在我们的示例中,当第一个导航堆栈位于弹出窗口下方时), Coordinator将忽略其中可能发出的步骤

从更一般的角度来看,仅在该的上下文中解释在的上下文中发出的步骤 (它们不能被其他捕获)。

DI是RxFlow的主要目标之一。 基本上,依赖注入可以通过将某种实现(服务,管理器等)作为参数传递给初始化程序或方法来完成(也可以通过属性来完成)。

RxFlow中 ,由于开发人员负责实例化UIViewControllers,ViewModels,Presenter等,因此这是注入所需内容的绝佳机会。 这是ViewModel中依赖项注入的示例。

现在您已经知道如何将事物组合在一起,混合流程步骤以触​​发导航动作并产生NextFlowItems ,剩下要做的一件事:在应用程序启动时引导导航过程。

一切都在AppDelegate中发生,并且您会发现这非常简单:

  • 实例化协调器
  • 实例化要导航的第一个流程
  • 要求协调员首先协调此流程
  • 当第一个Flow准备好时,将其根设置为Window的rootViewController

这是在演示应用程序中完成的方法。

协调器有两个响应式扩展: willNavigatedidNavigate 。 例如,您可以在AppDelegate中订阅它们。

这将产生这种日志:

did navigate flow=RxFlowDemo.MainFlow step=apiKeyIsComplete 
did navigate flow=RxFlowDemo.WishlistFlow step=movieList
did navigate flow=RxFlowDemo.WatchedFlow step=movieList
did navigate flow=RxFlowDemo.WishlistFlow step=moviePicked(23452) did navigate flow=RxFlowDemo.WishlistFlow step=castPicked(2)
did navigate flow=RxFlowDemo.WatchedFlow step=moviePicked(55423)
did navigate flow=RxFlowDemo.WatchedFlow step=castPicked(5)
did navigate flow=RxFlowDemo.WishlistFlow step=settings
did navigate flow=RxFlowDemo.SettingsFlow step=settings
did navigate flow=RxFlowDemo.SettingsFlow step=apiKey
did navigate flow=RxFlowDemo.SettingsFlow step=about
did navigate flow=RxFlowDemo.SettingsFlow step=apiKey
did navigate flow=RxFlowDemo.SettingsFlow step=settingsDone

对于分析和调试目的,它可能非常有帮助。

我希望您会发现此反应流协调器模式有趣且有用。 请随意贡献和挑战我的工作:GitHub上的RxFlow。