XRouter
只需一行代码即可导航到任何地方。
基本用法
配置
定义路由
enum AppRoute: RouteType {
case newsfeed
case login
case signup
case profile(userID: Int)
}
创建路由器
class Router: XRouter<AppRoute> {
override func prepareDestination(for route: AppRoute) throws -> UIViewController {
switch route {
case .newsfeed: return newsfeedController.rootViewController
case .login: return LoginFlowCoordinator().start()
case .signup: return SignupFlowCoordinator().start()
case .profile(let userID): return UserProfileViewController(withID: userID)
}
}
}
使用路由器
// Navigate directly to a route
router.navigate(to: .profile(3355))
// Open a URL
router.openURL(url)
高级用法
RxSwift
XRouter 默认支持 RxSwift 框架。存在用于 navigate(to:)
返回 Completable
的绑定,以及用于 openURL(_:)
返回 Single<Bool>
的绑定。
router.rx.navigate(to: .loginFlow) // -> Completable
router.rx.openURL(url) // -> Single<Bool>
深度链接支持
XRouter 提供了对深度链接和通用链接的支持。
您只需执行一项操作即可为您的路由添加 URL 支持。实现静态方法 registerURLs
enum AppRoute: RouteType {
static func registerURLs() -> URLMatcherGroup<Route>? {
return .group {
$0.map("/products") { .allProducts }
$0.map("/user/*/logout") { .logout }
$0.map("/products/{cat}/view") { try .products(category: $0.path("cat")) }
$0.map("/user/{id}/profile") {
try .viewProfile(withID: $0.path("id"), parameters: $0.query)
}
}
}
}
然后您可以调用 openURL(_:animated:completion:)
和/或 continue(_ userActivity:)
方法,例如从您的 AppDelegate 中调用
extension AppDelegate {
/// Handle deep links.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
return router.openURL(url, animated: false)
}
/// Handle universal links.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
return router.continue(userActivity)
}
}
您甚至可以定义更高级的 URL 路由。例如,这些规则可以用来匹配
http://example.com/login
-->.login
https://example.com/signup
-->.signup
customScheme://myApp/qr-code?code=abcdef...
-->.openQRCode("abcdef...")
https://www.example.com/products
-->.allProducts
https://api.example.com/user/my-user-name/logout
-->.logout
enum AppRoute: RouteType {
static func registerURLs() -> URLMatcherGroup<AppRoute>? {
return .init(matchers: [
.host("example.com") {
$0.map("/login") { .login }
$0.map("/signup") { .signup }
},
.scheme("customScheme") {
$0.map("/qr-code") { .openQRCode($0.query("code")) }
},
.group {
$0.map("/products") { .allProducts }
$0.map("/user/*/logout") { .logout }
}
])
}
}
错误处理
如果您以相同的方式处理所有的导航错误,您可以选择覆盖 received(unhandledError:)
方法。
class Router: XRouter<Route> {
override func received(unhandledError error: Error) {
log.error("Oh no! An error occured: \(error)")
}
}
或者您可以为某些单独的导航操作设置自定义的完成处理程序
router.navigate(to: .profilePage(withID: 24)) { (optionalError) in
if let error = optionalError {
print("Oh no, we couldn't go here because there was an error!")
}
}
自定义转场
这里使用流行的Hero Transitions库演示了一个例子。
定义你的自定义过渡动画
/// Hero cross fade transition
let heroCrossFade = RouteTransition { (source, dest, animated, completion) in
source.hero.isEnabled = true
dest.hero.isEnabled = true
dest.hero.modalAnimationType = .fade
// Present the hero animation
source.present(dest, animated: animated) {
completion(nil)
}
}
并在你的Router中将过渡设置为你的自定义过渡
override func transition(for route: AppRoute) -> RouteTransition {
if case Route.profile = route {
return heroCrossFade
}
return .automatic
}
文档
例子
要运行示例项目,请克隆仓库,然后在Xcode 10中运行。
要求
安装
CocoaPods
您可以通过CocoaPods获取XRouter。要安装它,请在Podfile中添加以下行
pod 'XRouter'
作者
Reece Como, [email protected]
许可证
XRouter可在MIT许可证下使用。更多信息请参阅LICENSE文件。