Simple Router for Swift based on Laravel’s Router, though it’s lacking Laravel’s advanced features like groups and everything that comes with them.
github "shnhrrsn/SHNUrlRouter" ~> 2.0.0
use_frameworks!
pod 'SHNUrlRouter', '~> 2.0.0'
Drag the *.swift
files from this repository into your project.
Setting up the router is as simple as defining a couple of routes and providing a handler to be triggered when they’re dispatched.
var router = UrlRouter()
router.register("feed") { [weak self] (parameters) in
self?.tabBarController.selectedIndex = 0
}
This will create a router and register a handler that switches to the first tab when the feed URL is dispatched.
You can specify route parameters to support more advanced routing:
router.register("user/{id}/{section?}") { [weak self] (parameters) in
// Non-optional parameters are guaranteed to be in the parameters
// dictionary, or the route won’t dispatch, so you can skip the
// usual guard let block if you’d like
let id = parameters["id"]!
let viewController = UserViewController(identifier: id)
// Optional parameters are not guaranteed, so you should handle
// their presence conditionally
if let section = parameters["section"] {
viewController.section = section
}
self?.tabBarController.presentViewController(viewController, animated: true, completion: nil)
}
Above we use the id
and section
parameters, however at this point they’re completely unconstrained and any path segment will match. You can use route aliases to specify a regex pattern that the parameters need to match:
// If your user IDs are numeric, you can use a numeric pattern to ensure you’ll always
// get a numeric id, otherwise the route won’t be dispatch
router.add("id", pattern: "[0-9]+")
// Similarly, if you want to ensure only specific sections dispatch, you can do that too
router.add("section", pattern: "profile|activity")
Dispatching routes is as simple as passing a URL to the router.
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
return self.router.dispatch(url)
}
SHNUrlRouter was built with support for full http://
links, with an eye towards iOS 9 and deep app linking. This means router is matching based on the path part of the URL and nothing else.
Prior to iOS 9, it was common for app’s to use a URL format like myapp://profile
. This won’t work with the router out of the box because the host
value is set to "profile" and not the path
value.
If you’re using a similar URL format for your app, you could use a quick/crude workaround as seen below until you’re ready to adopt full http linking:
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
if url.scheme == "myapp" {
if let url = url.absoluteString?.stringByReplacingOccurrencesOfString("://", withString: "://host/") {
return self.router.dispatch(url)
}
}
return false
}
class AppDelegate: UIResponder, UIApplicationDelegate {
private var router = UrlRouter()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject:AnyObject]?) -> Bool {
self.router.add("id", pattern: "[0-9]+")
self.router.add("section", pattern: "profile|activity")
self.router.register("feed") { [weak self] (parameters) in
self?.tabBarController.selectedIndex = 0
}
self.router.register("user/{id}/{section?}") { [weak self] (parameters) in
guard let stringId = parameters["id"], let id = Int(stringId) else {
return
}
let viewController = UserViewController(identifier: id)
if let section = parameters["section"] {
viewController.section = section
}
self?.tabBarController.presentViewController(viewController, animated: true, completion: nil)
}
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool {
return self.router.dispatch(url)
}
}
MIT — see the LICENSE file for more information.