MGDeeplinkNavigator 0.0.7

MGDeeplinkNavigator 0.0.7

测试已测试
语言语言 SwiftSwift
许可 MIT
发布最新版本2018年5月
SwiftSwift 版本4.0
SPM支持 SPM

Song 维护。



  • 作者
  • spf

DeeplinkNavigator

感谢 devxoul,本项目基于他/她的努力并结合启发而成。

Swift

DeeplinkNavigator 可以用于将 URL 模式映射为两种类型:DeeplinkNavigableDeeplinkOpenHandler。其中 DeeplinkNavigable 是一个协议,包含两个子协议:StoryboardNavigableInitNavigable(viewController 的默认初始化方法)。DeeplinkOpenHandler 是一个可以被调用的闭包,它接收一个 URL 和一些占位符值。

开始使用

1. 映射 URL 模式

URL 模式可以包含占位符。占位符将被从 URL 中匹配的值替换。使用 <> 来创建占位符。占位符可以有类型:string(默认),intfloatpath

以下是一个使用视图控制器和闭包来映射 URL 模式的例子。视图控制器应该遵守 DeeplinkNavigable 协议才能通过 URL 模式进行映射。

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
}

注意:全局常量 NavigatorDeeplinkNavigator.default 的快捷方式。

2. 推送、呈现和打开 URL

DeeplinkNavigator 可以使用 URL 推送和呈现视图控制器以及执行闭包。

push() 方法提供 from 参数来指定新视图控制器将被推入的 DeeplinkPushable。同样,为 present() 方法提供 from 参数来指定新视图控制器将被呈现的 DeeplinkPresentable。如果传递 nil(默认值),则使用当前应用的最顶层视图控制器来推送或呈现视图控制器。

present() 还有一个额外的参数:wrap。如果指定为 true,则新视图控制器将被包裹在一个 UINavigationController 中。默认值是 false

Navigator.push("myapp://user/123")
Navigator.present("myapp://post/54321", wrap: true)

Navigator.open("myapp://alert?title=Hello&message=World")

3. 实现 DeeplinkNavigable

视图控制器应该遵守 DeeplinkNavigable 协议以将其映射到 URL。一个 DeeplinkNavigable 协议定义了两个初始化协议:StoryboardNavigableInitNavigable,参数 navigation 包含了 urlvaluesmappingContextnavigationContext 作为属性。

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()
}
}

安装

pod 'DeeplinkNavigator'
github "LawrenceHan/DeeplinkNavigator"

技巧和窍门

URL映射位置

我更倾向于使用独立的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...
}
}

将UIView传递给push()或present()

有时你可能有一个多重窗口的情况,你可以传递一个UIView对象,让DeeplinkNavigator为你找到正确的UINavigationControllerUIViewController

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
Navigator.push("myapp://test", from: cell, animated: true)
}

使用pushOrPopTo扩展

你想push一个viewController,但又希望如果它已存在的话,弹出该viewController。

Navigator.popTo("myapp://user")
Navigator.pushOrPopTo("myapp://user/10")

实现AppDelegate启动选项URL

如果已注册自定义方案,则可以打开应用并使用URL。为了能够使用URL导航到viewController,需要实现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
}

实现 AppDelegate 打开 URL 方法

您可能需要实现自定义 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
}

设置默认方案

scheme 属性设置在 DeeplinkNavigator 实例上,可取消每个 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 文件。