ReactiveReSwiftRouter 4.0.0

ReactiveReSwiftRouter 4.0.0

测试已验证
语言语言 SwiftSwift
许可证 MIT
发布最后发布2017年12月
SwiftSwift 版本3.0
SPM支持 SPM

Richard Adem 维护。



Carthage compatible

Platform support

ReSwift 的声明式路由器。允许开发者以类似 Web 中使用 URL 的方式声明路由。

使用 ReSwiftRouter,您可以通过定义类似 URL 的标识符序列来定义目标位置以在应用程序中进行导航

mainStore.dispatch(
    SetRouteAction(["TabBarViewController", StatsViewController.identifier])
)

#关于 ReSwiftRouter

ReSwiftRouter 仍在开发中,API 目前既不完整也不稳定。

当使用 ReSwift 构建应用程序时,您应该旨在通过动作触发所有状态变化 - 这包括导航状态的变化。

这需要在应用程序状态中存储当前导航状态,并使用动作触发该状态的变化 - 这两点 ReSwiftRouter 都提供。

#安装

##CocoaPods

您可以通过将 ReSwiftRouter 添加到您的 Podfile 来使用 CocoaPods 进行安装

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/ReSwiftRouter"

##配置

扩展您的应用程序状态以包括导航状态

import ReSwiftRouter

struct AppState: StateType {
    // other application state
    var navigationState: NavigationState
}

初始化您的商店后,创建一个 Router 的实例,传入商店的引用和根 Routable。此外,您还需要提供一个描述如何访问应用程序状态的 navigationState 的闭包

router = Router(store: mainStore, rootRoutable: RootRoutable(routable: rootViewController)) { state in 
	state.navigationState
}

我们将在下一章讨论 Routable

##调用导航减法器

提供 NavigationReducer 作为 ReSwiftRouter 的一部分。您需要在顶级还原器中调用它。以下是一个简单的规范示例

struct AppReducer: Reducer {
    func handleAction(action: Action, state: FakeAppState?) -> FakeAppState {
        return FakeAppState(
            navigationState: NavigationReducer.handleAction(action, state: state?.navigationState)
        )
    }
}

这将使还原器处理所有与路由相关的动作。

#实现 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" 对应的视图。

当使用 UIKit 在 iOS 上工作时,这意味着 Routable 需要设置应用的重 rootViewController

每当 Routable 展示一个新的路由段时,它需要返回一个将负责管理展示段的新的 Routable。如果您想从 ["Home"] 导航到 ["Home", "Users"],负责 "Home" 段的 Routable 将会被要求展示 "User" 段。

如果您在此过渡中使用模态展示,则 "Home" 段的 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)
    }
    
    // ...
}

##在 Routables 中调用完成处理器

ReSwiftRouter 需要限制导航操作,因为许多 UI 框架(包括 UIKit)不允许并行执行多个导航步骤。因此,Routable 的每个方法都接收一个 completionHandler。只有在完成处理器被调用后,路由器才会执行任何其他导航操作。

#更改当前路由

目前更改当前应用路由的唯一方法是通过使用 SetRouteAction 并提供绝对路由。以下是一个简短的示例

@IBAction func cancelButtonTapped(sender: UIButton) {
    mainStore.dispatch(
        SetRouteAction(["TabBarViewController", StatsViewController.identifier])
    )
}

随着开发继续,将添加更改单个路由段的支持。

#投稿

##编译和运行测试

ReSwiftRouter 使用 Carthage 管理其开发依赖。要构建或测试任何目标,请运行 carthage bootstrap