一个用于 ReSwift 的声明式路由。 允许开发者以类似于在 Web 上使用 URL 的方式声明路由。
使用 ReSwiftRouter,您可以通过定义 URL 样式的标识符序列来导航您的应用程序。
mainStore.dispatch(
SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)
ReSwiftRouter 仍在开发中,API 在目前阶段既不完整也不稳定。
在使用 ReSwift 构建应用程序时,您应该旨在通过 actions 引起所有状态更改 - 这包括对导航状态的更改。
这需要将当前的导航状态存储在应用程序状态中,并使用 actions 来触发对该状态的更改 - ReSwiftRouter 提供了这两者。
您可以通过将 ReSwiftRouter 添加到您的 Podfile
来使用 CocoaPods 安装它
use_frameworks!
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
pod 'ReSwift'
pod 'ReSwiftRouter'
并运行 pod install
。
您可以通过将以下行添加到您的 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
。
NavigationReducer
作为 ReSwiftRouter
的一部分提供。 您需要在顶级 reducer 中调用它。 这是一个来自规范的简单示例
struct AppReducer: Reducer {
func handleAction(action: Action, state: FakeAppState?) -> FakeAppState {
return FakeAppState(
navigationState: NavigationReducer.handleAction(action, state: state?.navigationState)
)
}
}
这将使 reducer 处理所有与路由相关的 actions。
ReSwiftRouter 使用以类似于 URL 的方式定义的路由,作为一个元素序列,例如 ["Home", "User", "UserDetail"]
。
ReSwiftRouter 与您使用的 UI 框架无关 - 它使用 Routable
来实现这种交互。
每个路由元素都映射到一个负责的 Routable
。 Routable
需要能够呈现一个子视图,隐藏一个子视图,或用另一个子视图替换一个子视图。
这是 Routable
协议,其中包含您应该实现的方法
public protocol Routable {
func push(
_ element: RouteElement,
animated: Bool,
completion: @escaping RoutingCompletion) -> Routable
func pop(
_ element: RouteElement,
animated: Bool,
completion: @escaping RoutingCompletion)
func change(
_ from: RouteElement,
to: RouteElement,
animated: Bool,
completion: @escaping RoutingCompletion) -> Routable
}
作为初始化 Router
的一部分,您需要将第一个 Routable
作为参数传递。 根 Routable
将负责第一个路由元素。
例如,如果您将应用程序的路由设置为 ["Home"]
,则将要求您的根 Routable
呈现与元素 "Home"
相对应的视图。
如果在 iOS 上使用 UIKit,这将意味着 Routable
需要设置应用程序的 rootViewController
。
每当 Routable
呈现一个新的路由元素时,它需要返回一个新的 Routable
,它将负责管理呈现的元素。 如果您想从 ["Home"]
导航到 ["Home", "Users"]
,则将要求负责 "Home"
元素的 Routable
呈现 "User"
元素。
如果您的导航堆栈使用模态演示进行此转换,则 "Home"
元素的 Routable
实现可能如下所示
func push(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion) -> Routable {
if element == "User" {
// 1.) Perform the transition
userViewController = UIStoryboard(name: "Main", bundle: nil)
.instantiateViewControllerWithIdentifier("UserViewController") as! Routable
// 2.) Call the `completion` once the transition is complete
presentViewController(userViewController, animated: false,
completion: completion)
// 3.) Return the Routable for the presented element. For convenience
// this will often be the UIViewController itself.
return userViewController
}
// ...
}
func pop(_ element: RouteElement, animated: Bool, completion: @escaping RoutingCompletion)
if element == "Home" {
dismissViewControllerAnimated(false, completion: completion)
}
// ...
}
ReSwiftRouter 需要限制导航 actions,因为包括 UIKit 在内的许多 UI 框架不允许并行执行多个导航步骤。 因此,Routable
的每个方法都会收到一个 completion
handler。 在调用 completion handler 之前,路由器不会执行任何进一步的导航 actions。
目前,更改当前应用程序路由的唯一方法是使用 SetRouteAction
并提供绝对路由。 这是一个简短的例子
@IBAction func cancelButtonTapped(sender: UIButton) {
mainStore.dispatch(
SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)
}
随着开发的继续,将添加对更改单个路由元素的支持。
ReSwiftRouter 使用 Carthage 作为其开发依赖项。 要构建或测试任何目标,请运行 carthage bootstrap
。