ReSwift 的一种声明式路由器。允许开发者以类似网址的方式声明路由。
使用 ReSwiftRouter,您可以通过定义类似于网址的标识符序列来定义目标位置进行导航。
mainStore.dispatch(
SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)
关于 ReSwiftRouter
ReSwiftRouter 目前处于开发中,API 仍不完整且不稳定。
当使用 ReSwift 构建应用程序时,应旨在通过操作来引发所有状态改变 - 这包括导航状态的改变。
这需要在应用程序状态中存储当前的导航状态,并使用操作来触发该状态的变化 - 这两点 ReSwiftRouter 都能提供。
安装
CocoaPods
您可以通过将其添加到 Podfile
来通过 CocoaPods 安装 ReSwiftRouter
use_frameworks!
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'ReSwift'
pod 'ReSwiftRouter'
并且运行 pod install
Carthage
您可以通过在 Cartfile 中添加以下行来使用 Carthage 安装 ReSwiftRouter:
github "ReSwift/ReSwift-Router"
配置
扩展您的应用状态以包含导航状态
import ReSwiftRouter
struct AppState: StateType {
// other application state
var navigationState: NavigationState
}
初始化 store 之后,创建一个 Router
实例,传入 store 的引用和根 Routable
。您还需要提供一个闭包,描述如何访问应用程序状态中的 navigationState
router = Router(store: mainStore, rootRoutable: RootRoutable(routable: rootViewController)) { state in
state.select { $0.navigationState }
}
我们将在下一节介绍 Routable
。
调用导航 Reducer
NavigationReducer
是作为 ReSwiftRouter
的一部分提供的。您需要在顶层 reducer 中调用它。这里是一个来自规范的简单示例
struct AppReducer: Reducer {
func handleAction(action: Action, state: FakeAppState?) -> FakeAppState {
return FakeAppState(
navigationState: NavigationReducer.handleAction(action, state: state?.navigationState)
)
}
}
这将使 reducer 处理所有与路由相关的动作。
Routable
实现 ReSwiftRouter 与路由配合工作,这些路由类似于 URL,由一系列标识符组成,例如:["Home", "User", "UserDetail"]
。
ReSwiftRouter 对您使用的 UI 框架不敏感 - 它使用 Routable
来实现交互。
每个路由片段都映射到一个负责的 Routable
。该 Routable
需要能够呈现子视图、隐藏子视图或用另一个子视图替换子视图。
以下是包含您需要实现的方法的 Routable
协议
protocol Routable {
func changeRouteSegment(from: RouteElementIdentifier,
to: RouteElementIdentifier,
completionHandler: RoutingCompletionHandler) -> Routable
func pushRouteSegment(routeElementIdentifier: RouteElementIdentifier,
completionHandler: RoutingCompletionHandler) -> Routable
func popRouteSegment(routeElementIdentifier: RouteElementIdentifier,
completionHandler: RoutingCompletionHandler)
}
在初始化 Router
的过程中,您需要传递第一个 Routable
作为参数。该根 Routable
将负责第一个路由片段。
例如,如果您将应用程序的路由设置为 ["Home"]
,您的根 Routable
将被要求呈现与标识符 "Home"
对应的视图。
当在 iOS 和 UIKit 上工作的时候,这意味着该 Routable
需要设置应用程序的 rootViewController
。
每当一个 可路由
提供一个新的路由段时,它需要返回一个新的 可路由
,该路由将负责管理所提供的段。如果您想从 ["首页"]
导航到 ["首页", "用户"]
,将询问负责 "首页"
段的 可路由
提供的 "用户"
段。
如果你的导航堆栈在此过渡中使用了模态展示,负责 "首页"
段的 Routable
实现可能如下所示
func pushRouteSegment(identifier: RouteElementIdentifier,
completionHandler: RoutingCompletionHandler) -> Routable {
if identifier == "User" {
// 1.) Perform the transition
userViewController = UIStoryboard(name: "Main", bundle: nil)
.instantiateViewControllerWithIdentifier("UserViewController") as! Routable
// 2.) Call the `completionHandler` once the transition is complete
presentViewController(userViewController, animated: false,
completion: completionHandler)
// 3.) Return the Routable for the presented segment. For convenience
// this will often be the UIViewController itself.
return userViewController
}
// ...
}
func popRouteSegment(identifier: RouteElementIdentifier,
completionHandler: RoutingCompletionHandler) {
if identifier == "Home" {
dismissViewControllerAnimated(false, completion: completionHandler)
}
// ...
}
在可路由中调用完成处理程序
ReSwiftRouter 需要限制导航操作的数量,因为许多 UI 框架(包括 UIKit)不允许并行执行多个导航步骤。因此,可路由
的每个方法都接收一个 完成处理程序
。在完成处理程序被调用之前,路由器不会执行任何进一步的导航操作。
更改当前路由
当前更改当前应用程序路由的唯一方法是使用 SetRouteAction
并提供一个绝对路由。以下是一个简例:
@IBAction func cancelButtonTapped(sender: UIButton) {
mainStore.dispatch(
SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)
}
随着开发的进行,将添加更改单个路由段的功能。
贡献
编译和运行测试
ReSwiftRouter 使用 Carthage 进行其开发依赖。要构建或测试任何目标,请运行 carthage bootstrap
。