HDRoutes 0.3.0

HDRoutes 0.3.0

VanJay维护。



HDRoutes 0.3.0

  • 作者:
  • VanJay

HDRoutes

Platforms CocoaPods Compatible Build Status

它是什么?

注意

HDRoutes是Swift 5中JLRoutes的翻译版本,所有版权均归原作者所有。

HDRoutes是一个基于简单块级API的URL路由库。它旨在通过最少的代码轻松处理您的应用中的复杂URL模式。

安装

HDRoutes可以通过CocoaPods进行安装

pod 'HDRoutes'

需求

HDRoutes需要iOS 10.0及以上。

入门

在Info.plist中配置您的URL方案。

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 文件。