HDRoutes
它是什么?
注意
HDRoutes是Swift 5中JLRoutes的翻译版本,所有版权均归原作者所有。
HDRoutes是一个基于简单块级API的URL路由库。它旨在通过最少的代码轻松处理您的应用中的复杂URL模式。
安装
HDRoutes可以通过CocoaPods进行安装
pod 'HDRoutes'
需求
HDRoutes需要iOS 10.0及以上。
入门
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let routes = HDRoutes.globalRoutes()
routes?.addRoute(pattern: "/user/view/:userID", handler: { (params) -> Bool in
let userID = params["userID"] // defined in the route by specifying ":userID"
// present UI for viewing user with ID 'userID'
return true // return true to say we have handled the route
})
HDRoutes.verboseLoggingEnabled = true
HDRoutes.routesForScheme("ViPay")?.addRoute(pattern: "/test/:opt(/a)(/b)(/c)", priority: 10, handler: { (params) -> Bool in
print("打开测试页面\(params)")
return true
})
HDRoutes.globalRoutes()?.addRoute(pattern: "/test1", handler: { (params) -> Bool in
print("打开测试1页面\(params)")
return true
})
HDRoutes.routesForScheme("ViPay")?.unmatchedURLHandler = { _, _, _ in
print("无法识别的 ViPay 路由")
}
HDRoutes.globalRoutes()?.unmatchedURLHandler = { _, _, _ in
print("无法识别的路由")
}
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
_ = HDRoutes.routeURL(URL(string: "ViPay://test/:opt?a=6")!, parameters: ["name": "wangwanjie", "number": 5_201_314])
_ = HDRoutes.routeURL(URL(string: "/test1?age=27#topic")!, parameters: ["name": "wangwanjie", "number": 5_201_314])
_ = HDRoutes.routeURL(URL(string: "ViPay://8978998798q")!)
_ = HDRoutes.routeURL(URL(string: "jhkhjkkk")!)
}
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return HDRoutes.routeURL(url)
}
也可以使用下标语法注册路由
HDRoutes.globalRoutes()?.setHandlerBlock({ (params) -> Bool in
// ...
return true
}, forKeyedSubscript: "/user/view/:userID")
在添加 /user/view/:userID
路由后,以下调用将导致处理器块被调用于包含 @"userID": @"wangwanjie"
字典的情况。
let viewUserURL = URL(string: "myapp://user/view/wangwanjie")!
_ = HDRoutes.routeURL(viewUserURL)
参数字典
参数字典总是包含以下三个键。
{
"HDRoutesURL": "(the NSURL that caused this block to be fired)",
"HDRoutesPattern": "(the actual route pattern string)",
"HDRoutesNamespace": "(the route scheme, defaults to HDRoutesGlobalNamespace)"
}
HDRoutesNamespace
键指向匹配路由所在的方案。更多信息请参阅[方案](https://github.com/wangwanjie/HDRoutes#scheme-namespaces)。
有关常量的列表,请参阅HDRoutes.swift。
处理器块链
处理器块应该返回一个布尔值,以指示它是否处理了该路由。如果块返回 false
,HDRoutes 将像该路由不匹配一样进行操作,并继续寻找匹配项。只有当模式字符串匹配且块返回 true
时,路由才被认为是匹配的。
还应注意,如果您为处理器块传递 nil
,将创建一个内部处理器块,该块简单地返回 true
。
全局配置
有多个全局配置选项可供选择,以帮助为特定用例自定义 HDRoutes 的行为。所有选项仅对下一个操作生效。
/// Configures verbose logging. Defaults to false.
public static var verboseLoggingEnabled: Bool = false
/// Configures if '+' should be replaced with spaces in parsed values. Defaults to true.
public static var shouldDecodePlusSymbols: Bool = true
更复杂的示例
HDRoutes.globalRoutes()?.addRoute(pattern: "/:object/:action/:primaryKey", handler: { (params) -> Bool in
let object = params["object"]
let action = params["action"]
let primaryKey = params["primaryKey"]
// stuff
return true
})
这条路由会匹配类似于 /user/view/wangwanjie
或 /post/edit/123
的内容。假设您通过带有一些 URL 形参的 /post/edit/123
进行了调用。
let editPost = URL(string: "myapp://post/edit/123?debug=true&foo=bar")!
_ = HDRoutes.routeURL(editPost)
处理器块收到的参数字典将包含以下键/值对。
{
"object": "post",
"action": "edit",
"primaryKey": "123",
"debug": "true",
"foo": "bar",
"HDRoutesURL": "myapp://post/edit/123?debug=true&foo=bar",
"HDRoutesPattern": "/:object/:action/:primaryKey",
"HDRoutesNamespace": "HDRoutesGlobalNamespace"
}
方案
HDRoutes支持在特定URL方案内设置路由。方案内部设置的路由只能由使用匹配URL方案的路由匹配。默认情况下,所有路由都进入全局方案。
HDRoutes.globalRoutes()?.addRoute(pattern: "/foo", handler: { (params) -> Bool in
// This block is called if the scheme is not 'thing' or 'stuff' (see below)
return true
})
HDRoutes.routesForScheme("thing")?.addRoute(pattern: "/foo", handler: { (params) -> Bool in
// This block is called for thing://foo
return true
})
HDRoutes.routesForScheme("stuff")?.addRoute(pattern: "/foo", handler: { (params) -> Bool in
// This block is called for stuff://foo
return true
})
以下示例显示您可以在不同的方案中声明相同的路由,并针对每个方案使用不同的回调函数处理它们。
继续这个示例,如果您要添加以下路由
HDRoutes.globalRoutes()?.addRoute(pattern: "/global", handler: { (params) -> Bool in
return true
})
然后尝试路由URL thing://global
,它将不会匹配,因为该路由尚未在thing
方案中声明,而是在全局方案中(我们假设这是开发者想要的)。但是,您可以很容易地通过设置以下属性为true
来改变这种行为。
HDRoutes.routesForScheme("thing")?.shouldFallbackToGlobalRoutes = true
这告诉HDRoutes,如果在thing
方案(即,以thing:
开头但没有合适的路由可以找到)中无法路由URL,则尝试通过在全局路由方案中寻找匹配的路由来恢复。将该属性设置为true
后,URL thing://global
将被路由到/global
处理器块。
通配符
HDRoutes支持设置将会匹配任意数量路径分组的路由。包含附加路径分组的数组将以键kHDRoutesWildcardComponentsKey
添加到参数字典中。
例如,以下路由将触发以/wildcard/
开头的任何URL,但如果下一个组件不是joker
,则处理器将拒绝路由。
HDRoutes.globalRoutes()?.addRoute(pattern: "/wildcard/*", handler: { (params) -> Bool in
let pathComponents = params[kHDRoutesWildcardComponentsKey]
if let pathComponents = pathComponents as? [String], pathComponents.count > 0, pathComponents[0] == "joker" {
// the route matched; do stuff
return true
}
// not interested unless 'joker' is in it
return false
})
可选路由
HDRoutes支持设置具有可选参数的路由。在路由注册时,JLRoute将为带有和不带有可选参数的路由的多种组合注册多个路由。例如,对于路由 /the(/foo/:a)(/bar/:b)
,它将注册以下路由
/the/foo/:a/bar/:b
/the/foo/:a
/the/bar/:b
/the
查询路由
查询路由有多个方法,用于程序化使用(例如驱动调试用户界面)。有一个方法可以获取所有协议的路由集,另一个方法可以获取特定协议的路由列表。请注意,您需要导入 JLRRouteDefinition.h
,因为它已声明。
/// All registered routes, keyed by scheme
static func allRoutes() -> String
许可
BSD 3条款。详情见 LICENSE 文件。