介紹
- URLNavigator 是 devxoul發(fā)布在github上的一個(gè)Swift 路由庫
- 它提供了通過 URL 導(dǎo)航到 view controller 的方式
- 路由跳轉(zhuǎn)為的是模塊解耦
- 如果APP業(yè)務(wù)龐大厨钻,尤其是有一些H5打開原生界面的情況下贮缅,路由是一個(gè)非常好的打開業(yè)務(wù)的方式。
安裝
pod 'URLNavigator'
項(xiàng)目中使用
原始Demo中已經(jīng)有詳細(xì)的使用介紹聘芜。但是這里我打算做一些改動(dòng),按照業(yè)務(wù)模塊解耦不皆。
-
URLNavigator
的使用大致分為幾步:- 自定義路由URL
- 使用
Navigator
注冊路由蟆技,并確認(rèn)各路由URL對應(yīng)要打開的VC或者要處理的業(yè)務(wù) - 使用
Navigator
打開路由對應(yīng)業(yè)務(wù)
1. 自定義業(yè)務(wù)路由
//首頁模塊路由
enum HomeModuleRoute: String {
case homeRoute = "st://home"
case caseRoute = "st://cate/<int:cateId>"
//case searchRoute = "st://search/<string:keyword>" //string:可以不寫,默認(rèn)都是字符串
case searchRoute = "st://search/<keyword>"
case commonAlert = "st://alert"
}
//用戶模塊路由
enum UserModuleRoute: String {
case userHomeRoute = "st://userHome"
}
2. 定義 路由注冊器需要遵循的協(xié)議
protocol NavigationModulesProtocal {
//遵循此協(xié)議的各 路由注冊器 都要實(shí)現(xiàn)路由注冊方法
func initRoute(navigator: Navigator)
}
3. 實(shí)現(xiàn)各個(gè)業(yè)務(wù)模塊的路由注冊器
//首頁相關(guān)模塊 路由注冊器
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傳參時(shí)沿侈,可以獲取參數(shù)值
let title = url.queryParameters["title"]
let message = url.queryParameters["message"]
print("title:", title)
print("message:", message)
//接下來可以添加彈窗了闯第,略...
return true
}
}
}
//用戶相關(guān)模塊 路由注冊器
struct UserRouter: NavigationModulesProtocal {
func initRoute(navigator: Navigator) {
//注冊我的首頁
navigator.register(UserModuleRoute.userHomeRoute.rawValue) { url, values, context in
return UserHomeViewCtrl()
}
}
}
4. 創(chuàng)建一個(gè)Nav
結(jié)構(gòu)體作為路由處理總部
-
Nav
中創(chuàng)建Navigator
的單例。接下來所有的路由注冊都用Navigator
單例
struct Nav {
static let share = Navigator()
//業(yè)務(wù)路由注冊器都存入此數(shù)組缀拭,用于后續(xù)進(jìn)行統(tǒng)一注冊的初始化工作
private static let modulesRouteArray : [NavigationModulesProtocal] = [
HomeRouter.init(),
UserRouter.init()
]
//注冊所有需要用到的業(yè)務(wù)路由
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)
}
}
//這里是復(fù)用了原始demo中的模塊咳短,就是當(dāng)路由是web鏈接時(shí)填帽,用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. 可以測試了。但是這里要介紹一下通過路由打開業(yè)務(wù)的三種方式
-
URLNavigator
的跳轉(zhuǎn)方式有三種:push
咙好,present
篡腌,open
-
push
和present
對應(yīng)navigator.register
注冊的路由,用于打開VC -
open
對應(yīng)navigator.handle
注冊的路由勾效,用于其他功能:譬如打開彈窗等
//常規(guī)打開方式
Nav.share.push(UserModuleRouter.userHomeRouter.rawValue)
Nav.share.present(UserModuleRouter.userHomeRouter.rawValue)
//也可以通過 context 傳參數(shù)嘹悼。設(shè)置from從哪個(gè)界面跳轉(zhuǎn),不設(shè)置默認(rèn)從當(dāng)前控制器跳轉(zhuǎn)
Nav.share.push(UserModuleRouter.userHomeRouter.rawValue, context: ["param1":"123"], from: nil, animated: true)
//還可以使用它的直接打開控制器的方法
func pushViewController(_ viewController: UIViewController, from: UINavigationControllerType?, animated: Bool) -> UIViewController?
//有時(shí)候需要傳參层宫,可能就要使用路由的字符串字面量了杨伙。有沒有更好的辦法?可以留言指點(diǎn)萌腿,thanks~
Nav.share.push("st://cate/1000")
//打印結(jié)果:
url: st://cate/1000
values: ["cateId": 1000]
context nil
//有時(shí)候需要傳參限匣,可能就要使用路由的字符串字面量了。有沒有更好的辦法毁菱?可以留言指點(diǎn)米死,thanks~
Nav.share.push("st://home?title=溫馨提示&message=內(nèi)容", context: ["param1":"111"])
//打印結(jié)果:
url: st://home?title=溫馨提示&message=內(nèi)容
values: [:]
context Optional(["param1": "111"])
title: Optional("溫馨提示")
message: Optional("內(nèi)容")
//使用open方式打開
Nav.share.open("st://alert?title=溫馨提示&message=內(nèi)容", context: ["param1":"111"])
//打印結(jié)果:
url: st://home?title=溫馨提示&message=內(nèi)容
values: [:]
context Optional(["param1": "111"])
title: Optional("溫馨提示")
message: Optional("內(nèi)容")