介绍
- URLNavigator 是 devxoul发布在github上的一个Swift 路由库
- 它提供了通过 URL 导航到 view controller 的方式
- 路由跳转为的是模块解耦
- 如果APP业务庞大,尤其是有一些H5打开原生界面的情况下,路由是一个非常好的打开业务的方式。
安装
pod 'URLNavigator'
项目中使用
原始Demo中已经有详细的使用介绍。但是这里我打算做一些改动,按照业务模块解耦。
-
URLNavigator
的使用大致分为几步:- 自定义路由URL
- 使用
Navigator
注册路由,并确认各路由URL对应要打开的VC或者要处理的业务 - 使用
Navigator
打开路由对应业务
1. 自定义业务路由
//首页模块路由
enum HomeModuleRoute: String {
case homeRoute = "st://home"
case caseRoute = "st://cate/<int:cateId>"
//case searchRoute = "st://search/<string:keyword>" //string:可以不写,默认都是字符串
case searchRoute = "st://search/<keyword>"
case commonAlert = "st://alert"
}
//用户模块路由
enum UserModuleRoute: String {
case userHomeRoute = "st://userHome"
}
2. 定义 路由注册器需要遵循的协议
protocol NavigationModulesProtocal {
//遵循此协议的各 路由注册器 都要实现路由注册方法
func initRoute(navigator: Navigator)
}
3. 实现各个业务模块的路由注册器
//首页相关模块 路由注册器
struct HomeRouter: NavigationModulesProtocal {
func initRoute(navigator: Navigator) {
//注册首页
navigator.register(HomeModuleRoute.homeRoute.rawValue) { url, values, context in
print("url:", url)
print("values:", values)
print("context", context)
return HomeViewCtrl()
}
navigator.register(HomeModuleRoute.caseRoute.rawValue) { url, values, context in
print("url:", url)
print("values:", values)
print("context", context)
return CateViewCtrl()
}
navigator.register(HomeModuleRoute.searchRoute.rawValue) { url, values, context in
print("url:", url)
print("values:", values)
print("context", context)
return SearchViewCtrl()
}
navigator.handle(HomeModuleRoute.commonAlert.rawValue) { url, values, context in
print("url:", url)
print("values:", values)
print("context", context)
//通过url传参时,可以获取参数值
let title = url.queryParameters["title"]
let message = url.queryParameters["message"]
print("title:", title)
print("message:", message)
//接下来可以添加弹窗了,略...
return true
}
}
}
//用户相关模块 路由注册器
struct UserRouter: NavigationModulesProtocal {
func initRoute(navigator: Navigator) {
//注册我的首页
navigator.register(UserModuleRoute.userHomeRoute.rawValue) { url, values, context in
return UserHomeViewCtrl()
}
}
}
4. 创建一个Nav
结构体作为路由处理总部
-
Nav
中创建Navigator
的单例。接下来所有的路由注册都用Navigator
单例
struct Nav {
static let share = Navigator()
//业务路由注册器都存入此数组,用于后续进行统一注册的初始化工作
private static let modulesRouteArray : [NavigationModulesProtocal] = [
HomeRouter.init(),
UserRouter.init()
]
//注册所有需要用到的业务路由
static func initBusiness() {
self.share.register("http://<path:_>", self.webViewControllerFactory)
self.share.register("https://<path:_>", self.webViewControllerFactory)
//这里初始化所有的模块的路由注册
for router in modulesRouteArray {
router.initRoute(navigator: self.share)
}
}
//这里是复用了原始demo中的模块,就是当路由是web链接时,用webview打开
private static func webViewControllerFactory(url: URLConvertible, values: [String: Any], context: Any?) -> UIViewController? {
guard let url = url.urlValue else {
return nil
}
return SFSafariViewController(url: url)
}
}
5. 初始化路由
- 可以在
AppDelegate.swift
中初始化
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Nav.initBusiness()
return true
}
6. 可以测试了。但是这里要介绍一下通过路由打开业务的三种方式
-
URLNavigator
的跳转方式有三种:push
,present
,open
-
push
和present
对应navigator.register
注册的路由,用于打开VC -
open
对应navigator.handle
注册的路由,用于其他功能:譬如打开弹窗等
//常规打开方式
Nav.share.push(UserModuleRouter.userHomeRouter.rawValue)
Nav.share.present(UserModuleRouter.userHomeRouter.rawValue)
//也可以通过 context 传参数。设置from从哪个界面跳转,不设置默认从当前控制器跳转
Nav.share.push(UserModuleRouter.userHomeRouter.rawValue, context: ["param1":"123"], from: nil, animated: true)
//还可以使用它的直接打开控制器的方法
func pushViewController(_ viewController: UIViewController, from: UINavigationControllerType?, animated: Bool) -> UIViewController?
//有时候需要传参,可能就要使用路由的字符串字面量了。有没有更好的办法?可以留言指点,thanks~
Nav.share.push("st://cate/1000")
//打印结果:
url: st://cate/1000
values: ["cateId": 1000]
context nil
//有时候需要传参,可能就要使用路由的字符串字面量了。有没有更好的办法?可以留言指点,thanks~
Nav.share.push("st://home?title=温馨提示&message=内容", context: ["param1":"111"])
//打印结果:
url: st://home?title=温馨提示&message=内容
values: [:]
context Optional(["param1": "111"])
title: Optional("温馨提示")
message: Optional("内容")
//使用open方式打开
Nav.share.open("st://alert?title=温馨提示&message=内容", context: ["param1":"111"])
//打印结果:
url: st://home?title=温馨提示&message=内容
values: [:]
context Optional(["param1": "111"])
title: Optional("温馨提示")
message: Optional("内容")