NoMoreDeepLinkHandler SDK 允许应用管理处理打开应用的 URL 处理器。这个 URL 可以是 方案 URL 或 通用链接。NoMoreDeepLinkHandler SDK 中的 DeepLinkHandler
是通过 插件机制 设计的,以便可扩展。
NoMoreDeepLinkHandler 处理深链接时,将扫描所有已安装的处理程序,并将该深链接转发给相应的处理程序。这个过程将 顺序 发生,直到找到第一个匹配的处理程序。否则,将调用 notFoundHandler
。
每个处理程序遵守 DeepLinkHandlerPlugin
协议。
public protocol DeepLinkHandlerPlugin {
var completionTimeout: TimeInterval { get }
func shouldHandleDeepLink(_ url: URL) -> DeepLinkHandlerOption
func handleDeepLink(with data: Data?, completion: @escaping () -> Void)
}
-
如果处理程序在
completionTimeout
之前被选中,它将有一段时间来处理深链接。 -
shouldHandleDeepLink
方法决定此插件是否会处理深链接。有三种DeepLinkHandlerOption
选项。- no:插件拒绝处理深链接。处理深链接时将忽略它。
- yes(data: Data?): 插件接受处理深链接,数据应从深链接参数编码。
- yesWithBarrier(name: String, data: Data?): 插件接受处理深链接,但它必须通过一个以名称安装在 DeepLinkHandler 中的 Barrier。这对于需要由登录用户进行身份验证的深链接很有用。
-
当插件确认处理深链接时,将调用
handleDeepLink
方法。data
是从深链接解析的参数,它应从shouldHandleDeepLink
方法传递。通常,插件打开一个与深链接对应的上下文。最后,完成时调用completion
。
NoMoreDeepLinkHandler 包含在 MobileNext 标准库中,并在私有 Podspec 中可用。
# Install NoMoreDeepLinkHandler directly
pod "NoMoreDeepLinkHandler", "~> 1.0"
要处理深链接 app:///pay?order_id=123
,请创建一个 DeepLinkHandlerPlugin
。
final class PaymentDeepLinkHandlerPlugin: DeepLinkHandlerPlugin {
func shouldHandleDeepLink(_ url: URL) -> DeepLinkHandlerOption {
switch url.path {
case "pay":
let data = url.deepLinkExtensions.queryData
return .yes(data: data)
default:
return .no
}
}
func handleDeepLink(with data: Data?, completion: @escaping () -> Void) {
present(paymentConfirmScreen, with: data, completion: completion)
}
}
NoMoreDeepLinkHandler 必须在使用前初始化。这应该在应用启动时发生。
DeepLinkHandler.configure()
.install(plugin: PaymentDeepLinkHandlerPlugin())
.initialize()
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return DeepLinkHandler.shared.handle(deepLink: url)
}
许多深链接需要登录用户。因此,我们需要为此设置一个 AuthenticationDeepLinkBarrier
。
final class AuthenticationDeepLinkBarrier: DeepLinkHandlingBarrier {
func status(for deepLink: URL) -> DeepLinkBarrierStatus {
AccessToken.isValid ? .passed : .needToCheck
}
func performCheck(deepLink _: URL, completion: @escaping (Bool) -> Void) {
// Navigate to Login screen
present(loginScreen, callbackHandler: { data in
completion(data != nil)
})
}
}
DeepLinkHandler.configure()
.install(plugin: PaymentDeepLinkHandlerPlugin())
.install(barrier: AuthenticationDeepLinkBarrier())
.initialize()
例如,使用障碍配置上述付款处理程序。
final class PaymentDeepLinkHandlerPlugin: DeepLinkHandlerPlugin {
func shouldHandleDeepLink(_ url: URL) -> DeepLinkHandlerOption {
switch url.path {
case "pay":
let data = url.deepLinkExtensions.queryData
return .yesWithBarrier(AuthenticationDeepLinkBarrier.self, data: data)
default:
return .no
}
}
func handleDeepLink(with data: Data?, completion: @escaping () -> Void) {
present(paymentConfirmScreen, with: data, completion: completion)
}
}
打开付款 URL ⏩ 检查障碍是否通过 ⏩ 打开付款屏幕
有时,您需要在单个插件中处理一组深层链接,或者您需要预先处理查询数据以进行分类从URL中获取的查询数据。通过这种方式,DeepLinkHandlerPlugin
定义关联的参数类型,然后您可以在handleDeepLink
时通过该参数进行切换。因此,您不需要符合DeepLinkHandlerPlugin
规范,而是需要符合DeepLinkHandlerCodingPlugin
规范。
例如,您需要处理以下两个Payment深层链接
app:///pay?order_id=123
app:///transaction/789
,其中789是transaction_id
enum PaymentDeepLinkPoint: Codable {
case makePayment(data: Data?)
case transaction(id: String?)
init?(url: URL) {
let paths = url.deepLinkExtensions.pathComponents
var iterator = paths.makeIterator()
switch (iterator.next(), iterator.next()) {
case ("pay", nil):
self = .makePayment(data: url.deepLinkExtensions.queryData)
case ("transaction", let transactionID?):
self = .transaction(id: transactionID)
default:
return nil
}
}
}
final class PaymentDeepLinkHandlerPlugin: DeepLinkHandlerCodingPlugin {
func shouldHandleCodingDeepLink(_ url: URL) -> DeepLinkHandlerCodingOption<PaymentDeepLinkPoint> {
guard let point = PaymentDeepLinkPoint(url: url) else {
return .no
}
return .yesWithBarrier(AuthenticationDeepLinkBarrier.self, parameters: point)
}
func handleCodingDeepLink(with parameters: PaymentDeepLinkPoint, completion: @escaping () -> Void) {
switch parameters {
case let .makePayment(data):
present(paymentConfirmScreen, with: data, completion: completion)
case let .transaction(id):
present(transactionDetailScreen, with data: id?.data(using: .utf8), completion: completion)
}
}
}
定义一个具有动态参数的DeepLinkHandlerPlugin
参数在URL路径中。
了解更多关于 路径参数
👉 使用DeepLinkHandlerPathMatchingPlugin
协议而不是DeepLinkHandlerPlugin
。
例如,您需要处理以下Transaction深层链接
app:///transaction/789
final class TransactionDeepLinkPlugin: DeepLinkHandlerPathMatchingPlugin {
var matchingPath: String {
// Return path parameters pattern here
"/transaction/{transaction_id}"
}
func handleDeepLink(with data: Data?, completion: @escaping () -> Void) {
// The data is the encoded value of ["transaction_id": "789"]
present(transactionDetailScreen, completion: completion)
}
}
- notFoundHandler:没有注册适当处理器的处理程序时调用的处理器。
DeepLinkHandler.configure()
.withNotFoundHandler({ url in
// Open not found screen
})
.install(plugin: PaymentDeepLinkHandlerPlugin())
.initialize()
-
excludedSchemes和excludedHosts:将筛选出将不会被NoMoreDeepLinkHandler处理的方案和主机。
-
blacklistSchemes和blacklistHosts和whitelistHosts和whitelistSchemes:在处理深层链接之前进行筛选,如果设置了此字段的值,则仅处理白名单中的主机或方案。否则,将调用forbiddenHandler。优先级是
blacklist
>>whitelist
。
DeepLinkHandler.configure()
.set(blacklistHosts: ["localhost"])
.set(whitelistSchemes: ["first-scheme", "second-sechme"])
.set(whitelistHosts: ["sample-domain.vn"])
.with(forbiddenHandler: { url in
print("The deep link is forbidden: \(url)")
})
...
.initialize()
- mandatoryBarrier:在处理深层链接之前,所有深层链接必须通过的所有障碍。
这对于需要用户登录才能使用所有其他功能的App可能很有用。
DeepLinkHandler.configure()
.set(mandatoryBarrier: AuthenticationDeepLinkBarrier())
...
.initialize()