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