测试已测试 | ✗ |
Lang语言 | SwiftSwift |
许可证 | MIT |
Released上次发布 | 2017年8月 |
SwiftSwift版本 | 3.1 |
SPM支持SPM | ✓ |
由LawrenceHan维护。
DeeplinkNavigator 可以通过 2 种类型的类型使用 URL 模式进行映射:DeeplinkNavigable
和 DeeplinkOpenHandler
。DeeplinkNavigable
是一个协议,具有 2 个子协议:StoryboardNavigable
、InitNavigable
(viewController 的默认初始化方法)。DeeplinkOpenHandler
是一个可以执行的闭包。初始化器和闭包都接收一个 URL 和占位符值。
URL 模式可以包含占位符。占位符将被替换为从 URL 中匹配的值。使用 <
和 >
创建占位符。占位符可以具有类型:`string`(默认)、`int`、`float` 和 `path`。
以下是将 URL 模式映射到 view controller 和闭包的示例。要使用 URL 模式进行映射,viewController 应符合 DeeplinkNavigable
协议。
Navigator.map("myapp://user/<int:id>", UserViewController.self)
Navigator.map("myapp://post/<title>", PostViewController.self)
Navigator.map("myapp://alert") { url, values in
print(url.queryParameters["title"])
print(url.queryParameters["message"])
return true
}
注意:全局常量
Navigator
是 `DeeplinkNavigator.default
的快捷方式。
DeeplinkNavigator 可以使用 URL 推送并呈现 view controller,并且可以执行闭包。
在 push()
中提供 from
参数,以指定将推送的新 view controller 的 DeeplinkPushable
。类似地,向 present()
提供 from
参数,以指定将被呈现的新 view controller 的 DeeplinkPresentable
。如果传入 nil
,这是默认值,则使用当前应用程序的最高级 view controller 以推送或呈现 view controller。
present()
需要一个额外的参数:`wrap`。如果指定为 `true`,则新 view controller 将被包装在 `UINavigationController
` 中。默认值为 `false`。
Navigator.push("myapp://user/123")
Navigator.present("myapp://post/54321", wrap: true)
Navigator.open("myapp://alert?title=Hello&message=World")
视图控制器应遵守协议DeeplinkNavigable
以与URL进行映射。协议DeeplinkNavigable
定义了2个初始化协议:StoryboardNavigable
和InitNavigable
,其中navigation
参数包含作为属性的url
、values
、mappingContext
和navigationContext
。
属性url
是从DeeplinkNavigator.push()
和DeeplinkNavigator.present()
传递的URL。values
是一个字典,包含URL占位符键和值。mappingContext
是map()
函数传递的上下文。navigationContext
是一个包含从push()
或present()
传递的额外值的字典。
final class StoryboardViewController: UIViewController {
}
extension StoryboardViewController: StoryboardNavigable {
static func viewControllerFromStoryBoard(navigation: DeeplinkNavigation) -> UIViewController? {
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: String(describing: self))
return vc
}
}
final class XibViewController: UIViewController {
}
extension XibViewController: InitNavigable {
convenience init?(navigation: DeeplinkNavigation) {
self.init()
}
}
final class InitViewController: UIViewController {
}
extension InitViewController: InitNavigable {
convenience init?(navigation: DeeplinkNavigation) {
self.init()
}
}
CocoaPods
pod 'DeeplinkNavigator'
Carthage
github "LawrenceHan/DeeplinkNavigator"
我更愿意使用独立的URL映射文件。
struct NavigationMap {
static func initialize() {
Navigator.map("myapp://user/<int:id>", UserViewController.self)
Navigator.map("myapp://post/<title>", PostViewController.self)
Navigator.map("myapp://alert") { url, values in
print(url.queryParameters["title"])
print(url.queryParameters["message"])
self.someUtilityMethod()
return true
}
}
private static func someUtilityMethod() {
print("This method is really useful")
}
}
然后在AppDelegate的application:didFinishLaunchingWithOptions:
中调用initialize()
。
@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
// Navigator
URLNavigationMap.initialize()
// Do something else...
}
}
push()
或present()
有时你可能有一个多窗口层次结构的情况,你可以传递一个UIView对象,并由DeeplinkNavigator为你寻找正确的UINavigationController
或UIViewController
。
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
Navigator.push("myapp://test", from: cell, animated: true)
}
pushOrPopTo
扩展你可能想要推一个viewController,但你也想如果它已经存在,就弹出该viewController。
Navigator.popTo("myapp://user")
Navigator.pushOrPopTo("myapp://user/10")
如果已注册自定义方案,则可以使用URL打开您的应用。为了使用URL导航到视图控制器,您必须实现application:didFinishLaunchingWithOptions:
方法。
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
// ...
if let url = launchOptions?[.url] as? URL {
if let opened = Navigator.open(url)
if !opened {
Navigator.push(url)
}
}
return true
}
你可能想实现自定义URL打开处理器。这里是一个使用DeeplinkNavigator和其他URL打开处理器的示例。
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
// If you're using Facebook SDK
let fb = FBSDKApplicationDelegate.sharedInstance()
if fb.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation) {
return true
}
// DeeplinkNavigator Handler
if Navigator.open(url) {
return true
}
// DeeplinkNavigator View Controller
if Navigator.present(url, wrap: true) != nil {
return true
}
return false
}
在DeeplinkNavigator实例上设置scheme
属性以从每个URL中删除方案。
Navigator.scheme = "myapp"
Navigator.map("/user/<int:id>", UserViewController.self)
Navigator.push("/user/10")
这完全等同于
Navigator.map("myapp://user/<int:id>", UserViewController.self)
Navigator.push("myapp://user/10")
设置scheme
属性不会影响已经包含方案的现有其他URL。
Navigator.scheme = "myapp"
Navigator.map("/user/<int:id>", UserViewController.self) // `myapp://user/<int:id>`
Navigator.map("http://<path>", MyWebViewController.self) // `http://<path>`
let context = Foo()
Navigator.map("myapp://user/10", UserViewController.self, context: context)
let context: [AnyHashable: Any] = [
"fromViewController": self
]
Navigator.push("myapp://user/10", context: context)
Navigator.present("myapp://user/10", context: context)
DeeplinkNavigator是在MIT许可证下。请参阅LICENSE文件以获取更多信息。