[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6981":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":27,"readmeContent":28,"aiSummary":29,"trendingCount":16,"starSnapshotCount":16,"syncStatus":30,"lastSyncTime":31,"discoverSource":32},6981,"URLNavigator","devxoul\u002FURLNavigator","devxoul","⛵️ Elegant URL Routing for Swift","",null,"Swift",3347,299,50,38,0,5,59.93,"MIT License",false,"master",[23,24,25,26],"deeplink","ios","routing","swift","2026-06-12 04:00:31","# URLNavigator\n\n![Swift](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSwift-5.0-orange.svg)\n[![CocoaPods](http:\u002F\u002Fimg.shields.io\u002Fcocoapods\u002Fv\u002FURLNavigator.svg)](https:\u002F\u002Fcocoapods.org\u002Fpods\u002FURLNavigator)\n[![Build Status](https:\u002F\u002Fgithub.com\u002Fdevxoul\u002FURLNavigator\u002Fworkflows\u002FCI\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fdevxoul\u002FURLNavigator\u002Factions)\n[![CodeCov](https:\u002F\u002Fimg.shields.io\u002Fcodecov\u002Fc\u002Fgithub\u002Fdevxoul\u002FURLNavigator.svg)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fdevxoul\u002FURLNavigator)\n\n⛵️ URLNavigator provides an elegant way to navigate through view controllers by URLs. URL patterns can be mapped by using `URLNavigator.register(_:_:)` function.\n\nURLNavigator can be used for mapping URL patterns with 2 kind of types: `URLNavigable` and `URLOpenHandler`. `URLNavigable` is a type which defines an custom initializer and `URLOpenHandler` is a closure which can be executed. Both an initializer and a closure receive an URL and placeholder values.\n\n\n## Getting Started\n\n#### 1. Understanding URL Patterns\n\nURL patterns can contain placeholders. Placeholders will be replaced with matching values from URLs. Use `\u003C` and `>` to make placeholders. Placeholders can have types: `string`(default), `int`, `float`, and `path`.\n\nFor example, `myapp:\u002F\u002Fuser\u002F\u003Cint:id>` matches with:\n\n* `myapp:\u002F\u002Fuser\u002F123`\n* `myapp:\u002F\u002Fuser\u002F87`\n\nBut it doesn't match with:\n\n* `myapp:\u002F\u002Fuser\u002Fdevxoul` (expected int)\n* `myapp:\u002F\u002Fuser\u002F123\u002Fposts` (different url structure)\n* `\u002Fuser\u002Fdevxoul` (missing scheme)\n\n#### 2. Mapping View Controllers and URL Open Handlers\n\nURLNavigator allows to map view controllers and URL open handlers with URL patterns. Here's an example of mapping URL patterns with view controllers and a closure. Each closures has three parameters: `url`, `values` and `context`.\n\n* `url` is an URL that is passed from `push()` and `present()`.\n* `values` is a dictionary that contains URL placeholder keys and values.\n* `context` is a dictionary which contains extra values passed from `push()`, `present()` or `open()`.\n\n```swift\nlet navigator = Navigator()\n\n\u002F\u002F register view controllers\nnavigator.register(\"myapp:\u002F\u002Fuser\u002F\u003Cint:id>\") { url, values, context in\n  guard let userID = values[\"id\"] as? Int else { return nil }\n  return UserViewController(userID: userID)\n}\nnavigator.register(\"myapp:\u002F\u002Fpost\u002F\u003Ctitle>\") { url, values, context in\n  return storyboard.instantiateViewController(withIdentifier: \"PostViewController\")\n}\n\n\u002F\u002F register url open handlers\nnavigator.handle(\"myapp:\u002F\u002Falert\") { url, values, context in\n  let title = url.queryParameters[\"title\"]\n  let message = url.queryParameters[\"message\"]\n  presentAlertController(title: title, message: message)\n  return true\n}\n```\n\n#### 3. Pushing, Presenting and Opening URLs\n\nURLNavigator can push and present view controllers and execute closures with URLs.\n\nProvide the `from` parameter to `push()` to specify the navigation controller which the new view controller will be pushed. Similarly, provide the `from` parameter to `present()` to specify the view controller which the new view controller will be presented. If the `nil` is passed, which is a default value, current application's top most view controller will be used to push or present view controllers.\n\n`present()` takes an extra parameter: `wrap`. If a `UINavigationController` class is specified, the new view controller will be wrapped with the class. Default value is `nil`.\n\n```swift\nNavigator.push(\"myapp:\u002F\u002Fuser\u002F123\")\nNavigator.present(\"myapp:\u002F\u002Fpost\u002F54321\", wrap: UINavigationController.self)\n\nNavigator.open(\"myapp:\u002F\u002Falert?title=Hello&message=World\")\n```\n\n\n## Installation\n\nURLNavigator officially supports CocoaPods only.\n\n**Podfile**\n\n```ruby\npod 'URLNavigator'\n```\n\n\n## Example\n\nYou can find an example app [here](https:\u002F\u002Fgithub.com\u002Fdevxoul\u002FURLNavigator\u002Ftree\u002Fmaster\u002FExample).\n\n1. Build and install the example app.\n2. Open Safari app\n3. Enter `navigator:\u002F\u002Fuser\u002Fdevxoul` in the URL bar.\n4. The example app will be launched.\n\n\n## Tips and Tricks\n\n#### Where to initialize a Navigator instance\n\n1. Define as a global constant:\n\n    ```swift\n    let navigator = Navigator()\n\n    class AppDelegate: UIResponder, UIApplicationDelegate {\n      \u002F\u002F ...\n    }\n    ```\n\n2. Register to an IoC container:\n\n    ```swift\n    container.register(NavigatorProtocol.self) { _ in Navigator() } \u002F\u002F Swinject\n    let navigator = container.resolve(NavigatorProtocol.self)!\n    ```\n\n3. Inject dependency from a composition root.\n\n\n#### Where to Map URLs\n\nI'd prefer using separated URL map file.\n\n```swift\nstruct URLNavigationMap {\n  static func initialize(navigator: NavigatorProtocol) {\n    navigator.register(\"myapp:\u002F\u002Fuser\u002F\u003Cint:id>\") { ... }\n    navigator.register(\"myapp:\u002F\u002Fpost\u002F\u003Ctitle>\") { ... }\n    navigator.handle(\"myapp:\u002F\u002Falert\") { ... }\n  }\n}\n```\n\nThen call `initialize()` at `AppDelegate`'s `application:didFinishLaunchingWithOptions:`.\n\n```swift\n@UIApplicationMain\nfinal class AppDelegate: UIResponder, UIApplicationDelegate {\n  func application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?\n  ) -> Bool {\n    \u002F\u002F Navigator\n    URLNavigationMap.initialize(navigator: navigator)\n    \n    \u002F\u002F Do something else...\n  }\n}\n```\n\n\n#### Implementing AppDelegate Launch Option URL\n\nIt's available to open your app with URLs if custom schemes are registered. In order to navigate to view controllers with URLs, you'll have to implement `application:didFinishLaunchingWithOptions:` method.\n\n```swift\nfunc application(\n  _ application: UIApplication,\n  didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?\n) -> Bool {\n  \u002F\u002F ...\n  if let url = launchOptions?[.url] as? URL {\n    if let opened = navigator.open(url)\n    if !opened {\n      navigator.present(url)\n    }\n  }\n  return true\n}\n\n```\n\n\n#### Implementing AppDelegate Open URL Method\n\nYou'll might want to implement custom URL open handler. Here's an example of using URLNavigator with other URL open handlers.\n\n```swift\nfunc application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {\n  \u002F\u002F If you're using Facebook SDK\n  let fb = FBSDKApplicationDelegate.sharedInstance()\n  if fb.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation) {\n    return true\n  }\n\n  \u002F\u002F URLNavigator Handler\n  if navigator.open(url) {\n    return true\n  }\n\n  \u002F\u002F URLNavigator View Controller\n  if navigator.present(url, wrap: UINavigationController.self) != nil {\n    return true\n  }\n\n  return false\n}\n```\n\n\n#### Passing Extra Values when Pushing, Presenting and Opening\n\n```swift\nlet context: [AnyHashable: Any] = [\n  \"fromViewController\": self\n]\nNavigator.push(\"myapp:\u002F\u002Fuser\u002F10\", context: context)\nNavigator.present(\"myapp:\u002F\u002Fuser\u002F10\", context: context)\nNavigator.open(\"myapp:\u002F\u002Falert?title=Hi\", context: context)\n```\n\n\n#### Defining custom URL Value Converters\n\nYou can define custom URL Value Converters for URL placeholders.\n\nFor example, the placeholder `\u003Cregion>` is only allowed for the strings `[\"us-west-1\", \"ap-northeast-2\", \"eu-west-3\"]`. If it doesn't contain any of these, the URL pattern should not match.\n\nAdd a custom value converter to the `[String: URLValueConverter]` dictionary on your instance of `Navigator`.\n\n```swift\nnavigator.matcher.valueConverters[\"region\"] = { pathComponents, index in\n  let allowedRegions = [\"us-west-1\", \"ap-northeast-2\", \"eu-west-3\"]\n  if allowedRegions.contains(pathComponents[index]) {\n    return pathComponents[index]\n  } else {\n    return nil\n  }\n}\n```\n\nWith the code above, for example, `myapp:\u002F\u002Fregion\u002F\u003Cregion:_>` matches with:\n- `myapp:\u002F\u002Fregion\u002Fus-west-1`\n- `myapp:\u002F\u002Fregion\u002Fap-northeast-2`\n- `myapp:\u002F\u002Fregion\u002Feu-west-3`\n\nBut it doesn't match with:\n- `myapp:\u002F\u002Fregion\u002Fca-central-1`\n\nFor additional information, see the [implementation](https:\u002F\u002Fgithub.com\u002Fdevxoul\u002FURLNavigator\u002Fblob\u002Fmaster\u002FSources\u002FURLMatcher\u002FURLMatcher.swift) of default URL Value Converters.\n\n\n## License\n\nURLNavigator is under MIT license. See the [LICENSE](LICENSE) file for more info.\n","URLNavigator 是一个为 Swift 开发的优雅 URL 路由库，主要用于 iOS 应用中通过 URL 来导航视图控制器。它支持定义 URL 模式并将其与特定的视图控制器或闭包关联起来，从而实现基于 URL 的页面跳转和处理逻辑。该库能够识别带占位符的 URL，并允许开发者根据 URL 参数动态创建视图控制器实例或执行自定义代码。适用于需要实现深度链接、跨模块导航等场景的应用程序开发，有助于提高应用内导航的灵活性和可维护性。",2,"2026-06-11 03:09:59","top_language"]