Route URL schemes easily.
Crossroad is an URL router focused on handling Custom URL Scheme. Using this, you can route multiple URL schemes and fetch arguments and parameters easily.
This library is developed in working time for Cookpad.
use_frameworks!
pod 'Crossroad'
github "giginet/Crossroad"
You can use DefaultRouter
to define route definitions.
Imagine to implement Pokédex on iOS. You can access somewhere via URL scheme.
router = DefaultRouter(scheme: "pokedex")
router.register([
("/pokemons", { context in
let type: Type? = context[parameter: "type"]
presentPokedexListViewController(for: type)
return true
}),
("/pokemons/:pokedexID", { context in
guard let pokedexID: Int? = context[argument: "pokedexID"] else {
// pokedexID must be Int
return false
}
if !Pokedex.isExist(pokedexID) { // Find the Pokémon by ID
return false
}
presentPokedexDetailViewController(of: pokedexID)
return true
}),
// ...
])
let canRespond25 = router.responds(to: URL(string: "pokedex://pokemons/25")!) // Pikachu(No. 25) is exist! so it returns true
let canRespond9999 = router.responds(to: URL(string: "pokedex://pokemons/9999")!) // No. 9999 is unknown. so it returns false
router.openIfPossible(URL(string: "pokedex://pokemons/25")!) // Open Pikachu page
router.openIfPossible(URL(string: "pokedex://pokemons?type=fire")!) // Open list of fire Pokémons page
You can also skip schemes on URLs. URLPattern /search/:keyword
means pokedex://search/:keyword
on the router.
In common use case, you should call router.openIfPossible
on UIApplicationDelegate
method.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool {
return router.openIfPossible(url, options: options)
}
Or, if you are using SceneDelegate
with a modern app:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let context = URLContexts.first else {
return
}
router.openIfPossible(context.url, options: context.options)
}
:
prefixed components on passed URL pattern mean argument.
For example, if passed URL matches pokedex://search/:keyword
, you can get keyword
from Context
.
// matches: pokedex://search/Pikachu
let keyword: String = context[argument: "keyword"] // Pikachu
And more, you can get query parameters if exist.
// matches: pokedex://search/Pikachu?generation=1
let generation: Int? = context[parameter: "generation"] // 1
Currently supported type is Int
, Int64
, Float
, Double
, Bool
, String
and URL
.
You can use enum as arguments by implementing Parsable
.
enum Type: String, Parsable {
case normal
case fire
case water
case grass
// ....
}
// matches: pokedex://pokemons?type=fire
let type: Type? = context[parameter: "type"] // .fire
You can treat comma-separated query strings as Array
.
// matches: pokedex://pokemons?types=water,grass
let types: [Type]? = context[parameter: "types"] // [.water, .grass]
You can also define own arguments by implementing Parsable
.
This is an example to parse custom struct.
struct User {
let name: String
}
extension User: Parsable {
init?(from string: String) {
self.name = string
}
}
You can add any payload to Router
.
struct UserInfo {
let userID: Int64
}
let router = Router<UserInfo>(scheme: "pokedex")
router.register([
("pokedex://pokemons", { context in
let userInfo: UserInfo = context.userInfo
let userID = userInfo.userID
return true
}),
// ...
])
let userInfo = UserInfo(userID: User.current.id)
router.openIfPossible(url, userInfo: userInfo)
You can make routers handle with Universal Links.
Of course, you can also use Firebase Dynamic Link or other similar services.
let router = DefaultRouter(url: URL(string: "https://my-awesome-pokedex.com")!)
If you maintain a complex application and you want to use independent URL pattern parsers without Router.
You can use URLParser
.
let parser = URLParser<Void>()
let context = parser.parse(URL(string: "pokedex:/pokemons/25")!,
in: "pokedex://pokemons/:id")
Latest version of Crossroad requires Swift 5.0 or above.
Use 1.x instead on Swift 4.1 or lower.
Crossroad Version | Swift Version | Xcode Version |
---|---|---|
3.x | 5.0 | Xcode 10.3 |
2.x | 5.0 | Xcode 10.2 |
1.x | 4.0 ~ 4.2 | ~ Xcode 10.1 |
Crossroad is released under the MIT License.
Header logo is released under the CC BY 4.0 license. Original design by @Arslanshn.