Wkwebview все еще не обрабатывает универсальную ссылку
У меня есть универсальная ссылка iOS, ориентированная на myApp
. Когда я нажимаю эту ссылку в другом приложении, myApp
открывается и отлично отображает правильный выигрыш, он работает.
Но myApp
включает встроенный браузер с использованием WKWebView
. Когда я нажимаю одну и ту же универсальную ссылку из встроенного браузера, iOS не отправляет ссылку на myApp
, она отправляет и выбирает веб-страницу.
Apple docs говорят
Если вы создаете экземпляр объекта SFSafariViewController, WKWebView или UIWebView для обработки универсальной ссылки, iOS открывает ваш сайт в Safari вместо открытия вашего приложения. Однако, если пользователь удаляет универсальную ссылку внутри встроенного объекта SFSafariViewController, WKWebView или UIWebView, iOS открывает ваше приложение.
Я отмечаю этот аналогичный вопрос, где было предложено определить делегата WKWebView
. У меня есть оба делегата WKWebView
, определенные и используемые в myApp
, и это не помогает. Этот другой вопрос имеет много вариантов, но ответов нет.
My WKWebView
может фактически открыть универсальные ссылки для других приложений. Если я нажму ссылку https://open.spotify.com/artist/3hv9jJF3adDNsBSIQDqcjp в пределах myApp
WKWebView
, тогда он откроет приложение для замещения без открытия какой-либо промежуточной веб-страницы (даже хотя меню с длинным нажатием в myApp
не предлагает "открыть в spotify" ). Но iOS не будет предоставлять универсальную ссылку на myApp
, когда я нажму на нее из myApp
.
После долгих испытаний я обнаружил, что я могу предотвратить отображение веб-страницы, связанной с универсальной ссылкой, путем поиска конкретного URL-адреса и отмены отображения:
func webView(webView: WKWebView, decidePolicyForNavigationResponse navigationResponse: WKNavigationResponse, decisionHandler: (WKNavigationResponsePolicy) -> Void) {
if let urlString = navigationResponse.response.URL?.absoluteString {
if urlString.hasPrefix(myULPrefix) { // it a universal link targetted at myApp
decisionHandler(.Cancel)
return
}
}
decisionHandler(.Allow)
}
Я должен сделать это в обработчике решения для ответа, а не в действии. Когда я это сделаю, универсальная ссылка поставлена в очередь для доставки до myApp
. НО это фактически не доставляется iOS, пока я не покину свое приложение (например, нажав кнопку "домой" ) и перезапустив его. Функция appDelegate
, указанная в качестве доставки этого сообщения в документах Apple, упомянутых выше
func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {}
не вызывается. Он вызывается, когда я делаю более обычный deeplink - щелкнув универсальную ссылку в Safari, чтобы открыть myApp
.
Это ошибка? Или особенность? Или я, как обычно, просто лаем неправильное дерево?
Спасибо!
Ответы
Ответ 1
Это будет поведение, если ваше доменное имя wpwebview wep будет таким же, как имя домена универсальной ссылки. В кадре, если веб-страница открыта в Safari, SFSafariVC, WKWebView или UIWebView имеют домен, такой же, как и ссылка на приложение (общедоступная ссылка), он не будет тигрировать универсальную ссылку,
Ответ 2
Я решил эту проблему с моим классом 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)
}
}
}