我有一个针对myApp
的iOS通用链接。当我在另一个应用中点击该链接时,myApp
会打开并完美显示正确的收益,它正在运行。
但myApp
包含使用WKWebView
的内置浏览器。当我从内置浏览器中点击相同的通用链接时,iOS不会将链接发送到myApp
,而是会提取并提取网页。
如果您实例化SFSafariViewController,WKWebView或UIWebView对象以处理通用链接,iOS将在Safari中打开您的网站,而不是打开您的应用程序。但是,如果用户点击嵌入式SFSafariViewController,WKWebView或UIWebView对象中的通用链接,iOS将打开您的应用程序。
我注意到这个similar question,其中的建议是定义WKWebView
代表。我在WKWebView
中定义并使用了myApp
个委托,但它没有帮助。这个other question有很多赞成但没有答案。
我的WKWebView
实际上可以打开其他应用的通用链接。如果我点击myApp
WKWebView
中的https://open.spotify.com/artist/3hv9jJF3adDNsBSIQDqcjp链接,则会打开spotify应用,而不会打开任何中间网页(即使myApp
中的长按菜单没有'提议“在spotify中打开”)。但是,当我从myApp
内点击它时,iOS将无法提供myApp
的通用链接。
经过大量测试后,我发现通过查找特定网址并取消显示,我可以阻止显示与通用链接相关联的网页:
func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {
if let urlString = navigationResponse.response.URL?.absoluteString {
if urlString.hasPrefix(myULPrefix) { // it's a universal link targetted at myApp
decisionHandler(.Cancel)
return
}
}
decisionHandler(.Allow)
}
我必须在响应的决策处理程序中执行此操作,而不是操作的决策处理程序。执行此操作时,通用链接 排队等待传递到myApp
。 BUT 在我退出我的应用程序之前(例如,通过按下主页按钮)并重新启动它,它实际上并未由iOS提供。 appDelegate
函数指定为在上面引用的Apple文档中传递此消息
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {}
未被调用。当我执行更传统的深层链接时, 被调用 - 单击Safari中的通用链接以打开myApp
。
这是一个错误吗?还是一个功能?或者我像往常一样,只是吠叫错误的树?
谢谢!
答案 0 :(得分:1)
如果您的wkwebview wep页面域名与您的通用链接域名称相同,则会出现这种情况。在镜头中,如果在Safari中打开网页,SFSafariVC,WKWebView或UIWebView具有与应用程序的应用程序链接(通用链接)域相同的域,则不会使用通用链接,
答案 1 :(得分:0)
我在下面的Swift 4类中解决了此问题。如果可能,它还会使用嵌入式Safari浏览器。您也可以按照类似的方法进行操作。
import UIKit
import SafariServices
class OpenLink {
static func inAnyNativeWay(url: URL, dontPreferEmbeddedBrowser: Bool = false) { // OPEN AS UNIVERSAL LINK IF EXISTS else : EMBEDDED or EXTERNAL
if #available(iOS 10.0, *) {
// Try to open with owner universal link app
UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey.universalLinksOnly : true]) { (success) in
if !success {
if dontPreferEmbeddedBrowser {
withRegularWay(url: url)
} else {
inAnyNativeBrowser(url: url)
}
}
}
} else {
if dontPreferEmbeddedBrowser {
withRegularWay(url: url)
} else {
inAnyNativeBrowser(url: url)
}
}
}
private static func isItOkayToOpenUrlInSafariController(url: URL) -> Bool {
return url.host != nil && (url.scheme == "http" || url.scheme == "https") //url.host!.contains("twitter.com") == false
}
static func inAnyNativeBrowser(url: URL) { // EMBEDDED or EXTERNAL BROWSER
if isItOkayToOpenUrlInSafariController(url: url) {
inEmbeddedSafariController(url: url)
} else {
withRegularWay(url: url)
}
}
static func inEmbeddedSafariController(url: URL) { // EMBEDDED BROWSER ONLY
let vc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
if #available(iOS 11.0, *) {
vc.dismissButtonStyle = SFSafariViewController.DismissButtonStyle.close
}
mainViewControllerReference.present(vc, animated: true)
}
static func withRegularWay(url: URL) { // EXTERNAL BROWSER ONLY
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [UIApplication.OpenExternalURLOptionsKey(rawValue: "no"):"options"]) { (good) in
if !good {
Logger.log(text: "There is no application on your device to open this link.")
}
}
} else {
UIApplication.shared.openURL(url)
}
}
}
答案 2 :(得分:0)
我认为 Apple 是这样设计的,因为当您的应用程序运行时发生这种情况时,您可以对其进行更可定制的处理。
您找到了放置您自己的处理程序调用的地方:
func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {
if let urlString = navigationResponse.response.URL?.absoluteString {
if urlString.hasPrefix(myULPrefix) { // it's a universal link targetted at myApp
decisionHandler(.Cancel)
// put here the call to handle the link, for example:
MyLinkHandler.handle(urlString)
return
}
}
decisionHandler(.Allow)
}
您可以在后台进行任何操作而用户停留在打开的页面上,或者您可以隐藏网络视图并打开应用程序的另一部分以显示适当的内容。