ReSwiftRouter 0.7.1

ReSwiftRouter 0.7.1

测试已经测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2019年7月
SPM支持 SPM

Benjamin EnczMalcolm JarvisChristian Tietze 维护。



  • 作者
  • Benjamin Encz

Carthage compatible Platform support

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