FlowState
FlowState
是一个轻量级的框架,用于创建 Swift 风格的可组合 Flow Coordinators。FlowState 采用了更函数式的方法来处理 ViewController/Coordinator 模式。您可以将它视为对 Promise 模式的扩展。
FlowState 提供了一组灵活易用的机制,可以
- 从 View Controllers 中移除所有业务逻辑
- 执行异步请求
- 将数据加载到 View Controllers 中,无需管道引用
- 帮助去除状态性
- 使 A/B 测试变得简单
- 创建可组合、可重新排列的流程
- 分割网络/建模/视图逻辑
它是如何工作的?
FlowState 有两个基本的构建块,它们相辅相成。即 FlowStep
和 FlowStepHandler
。您可以将 FlowStep
视为一个承诺和一个任务工厂。 FlowStepHandler
允许 FlowStep
完成,并管理信息路由。
一个 Flow
由一系列 FlowStep
对象组成。它们在链式列表堆栈中链接在一起。第一步开始,一旦这一步由其 FlowStepHandler
完成,第二步就开始,以此类推。
FlowStep
可以管理 View Controller、网络请求或嵌套的 Flow。
FlowStep
和 FlowStepHandler
都是泛型类,它们有两个泛型类型:Content
和 Result
。 Content
可以被视为步骤的输入。 Content
会自动从步骤路由到其 FlowStepHandler
,这使得管理数据流变得容易。 Result
可以被视为步骤的输出,这是步骤在继续之前试图收集的信息。当步骤提供其 Result
时,步骤完成。
流程步骤
让我们看看这个例子。
此示例显示流程中单个步骤的生命周期。协调器启动了一个流程步骤
。步骤的意图块分配了一个要显示在屏幕上的ViewController
。ViewController
拥有一个流程步骤处理器
,该处理器在意图块中返回给流程步骤
。
当用户选择一个选项时,ViewController
调用其流程步骤处理器
上的complete(option)
。然后处理器自动转发完成调用,步骤完成,并将结果路由回协调器。协调器可以处理这些结果,并使用start()
启动下一步。
这在代码中是什么样的?
示例
让我们创建一个简单的流程,用于从用户个人资料收集一些信息。
首先,让我们显示我们拥有的信息,显示用户个人资料。
流程步骤有两个主要部分,内容
,它定义了步骤显示的内容,以及
结果
,它定义了步骤收集的信息。有些步骤不收集信息,
而是交互。
此第一个步骤将显示用户个人资料视图控制器。用户个人资料视图控制器显示
由用户个人资料
结构体提供的信息。个人资料视图控制器希望在显示时刷新其内容
通过执行网络调用下载个人资料数据。此外,
个人资料视图控制器有一个按钮,允许用户更新他们的名字。
然后,个人资料视图控制器有两个结果操作,下载和updateName,每个都定义在
一个名为用户个人资料操作
的枚举中。
个人资料视图控制器还有一个它拥有的流程步骤处理器
,称为results
。
个人资料视图控制器使用results获取其内容,并根据用户的任何交互向意图通知。
/// Create a FlowStep that displays the profile view controller.
let displayStep = FlowStep(UserProfile.self, UserProfileAction.self, identifier: "Profile", { (step) in
/// This block is called each time the step begins.
/// Make a new Profile Display VC
let vc = UserProfileViewController()
/// Set the vc on the navigation controller step.
navigationController.setViewControllers([vc], animated: false)
/// Return the View Controller's FlowStepHandler `results`.
return vc.results
})
显示步骤有两个结果,一个将显示一个编辑用户名的视图控制器,
另一个将下载新的个人资料。
让我们创建一个用于下载新个人资料的步骤。此步骤没有内容,但结果是一个新的
用户个人资料
对象。
/// Create a step that downloads the user profile from the internet
let networkStep = FlowStep(Any.self, UserProfile.self, identifier: "User Profile Network", { (step) in
/// Show a loader View Controller
let loader = LoadingModalViewController()
navigationController.present(loader, animated: true, completion: nil)
/// Create step results for this step.
let stepResults = FlowStepHandler(Any.self, UserProfile.self)
/// Make an async network call.
UserProfile.getUser() { (newProfile) in
/// After the download has completed, call completion with the results.
stepResults.complete(newProfile)
}
return stepResults
}) { [unowned displayStep] (step, newProfile) in
if let newProfile = newProfile {
/// Set the new profilew on the display step, which automatically updates it's view controller.
displayStep.content = newProfile
}
/// Dismiss the loading modal.
navigationController.dismiss(animated: true, completion: nil)
}
现在让我们创建一个允许用户编辑其名字的步骤。
编辑名字视图控制器的内容类型为String
,结果类型为一个新
let editNameStep = FlowStep(String.self, String.self, identifier: "Edit Name", { (step) in
let vc = StringEntryViewController()
navigationController.pushViewController(vc, animated: true)
return vc.results
})
String
/// Create a step that updates the user profile
let updateNameStep = FlowStep(String.self, UserProfile.self, identifier: "Update Profile Step", { (step) in
/// Show a loader View Controller
let loader = LoadingModalViewController()
navigationController.present(loader, animated: true, completion: nil)
/// Create step results for this step.
let stepResults = FlowStepHandler(Any.self, UserProfile.self)
/// Make an async network call that updates the user profile with the step's content.
UserProfile.updateName(step.content) { (newProfile) in
/// After the download has completed, call completion with the results.
stepResults.complete(newProfile)
}
return stepResults
}) { [unowned displayStep] (step, newProfile) in
if let newProfile = newProfile {
/// Set the new profilew on the display step, which automatically updates it's view controller.
displayStep.content = newProfile
}
/// Dismiss the loading modal.
navigationController.dismiss(animated: true, completion: nil)
/// Optionally you could pop the nav controller here to go back to the profile.
}
接下来,让我们创建一个网络调用,更新用户名并返回更新的用户个人资料
现在让我们将editNameStep
链接到updateNameStep
首先,我们需要在editNameStep
中添加一个完成闭包,将其结果转发到updateNameStep
。
editNameStep.setCompletion { (step, newName) in
guard let newName = newName else {
step.nextStep = nil
return
}
/// Forward the results of this step to the updateNameStep
updateNameStep.content = newName
step.nextStep = updateNameStep
}
然后我们将editNameStep
的下一步设置为updateNameStep
。
/// Set the display step completion block to switch between its results
displayStep.setCompletion { (step, action) in
guard let action = action else { return }
switch action {
case .editProfile:
/// Edit profile was pressed.
editTextStep.content = step.content
step.nextStep = editTextStep
case .downloadProfile:
/// Download profile was pressed.
step.nextStep = fakeNetworkStep
}
}
最后,现在我们已经创建了所有步骤,让我们在管理UserProfileView
的步骤上设置分叉逻辑。
示例项目
还需要更多吗?
要运行示例项目,请首先克隆仓库,然后从示例目录中执行 pod install
。
需求
安装
FlowState可通过CocoaPods获得。要安装它,只需将以下行添加到您的Podfile中
将它
pod 'FlowState'
作者
buba447, [email protected]
许可证
FlowState在MIT许可证下提供。更多信息请参阅LICENSE文件。