首页 > 解决方案 > iOS14,WKWebView 无法打开带有 _blank 目标的链接

问题描述

我有 WKWebView,我想用它来浏览某个网站。

然而,一些带有 target="_blank" 的链接并不总是打开。从运行到运行,我得到不同的结果。

任何想法都将受到高度赞赏。

这是我的代码。WebViewStore 由 SwiftUI 视图使用,这就是它是 ObservableObject 的原因。

public class WebViewStore: NSObject, ObservableObject {
    @Published public var navDelegate = WebViewNavDelegate();
    @Published public var uiDelegate = WebViewUIDelegate();
    @Published public var webView: WKWebView = WKWebView() {
        didSet {
            log.info("WebViewStore.webView new WebView !!!")
            setupObservers()
        }
    }

    override public init() {
        super.init();
        log.info("WebViewStore.init")

        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true

        let configuration = WKWebViewConfiguration()
        configuration.websiteDataStore =  WKWebsiteDataStore.nonPersistent()
        configuration.preferences = preferences

        let webView = WKWebView(frame: CGRect.zero, configuration: configuration)
        webView.translatesAutoresizingMaskIntoConstraints = false
        webView.allowsLinkPreview = true
        webView.allowsBackForwardNavigationGestures = true
        webView.isUserInteractionEnabled = true

        webView.uiDelegate = uiDelegate;
        webView.navigationDelegate = navDelegate;
        self.webView = webView;
    }

这是仅对某些链接调用的 navDelegate!

public class WebViewNavDelegate : NSObject, WKNavigationDelegate, ObservableObject {
    public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        log.info("WebViewUI.webView : 6 - decidePolicyFor" )
        isLoading = true;

        log.info("url: \(navigationAction.request.url!.absoluteString)")
        log.info("target: \(navigationAction.targetFrame?.description)")
            
        // This allows the navigation
        decisionHandler(.allow)
    }
}

这是我的 uiDelegate。我希望在需要新视图时调用它,我会将它加载到原始视图中(相同)。

不幸的是,这个方法只是有时被调用......

public class WebViewUIDelegate : NSObject, WKUIDelegate {
    
    public func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
        log.info("WebViewUIDelegate.webView() (createWebViewWith)")
        
        log.info("url: \(navigationAction.request.url?.absoluteString)" )
        log.info("target: \(navigationAction.targetFrame)" )

        if navigationAction.targetFrame == nil {
            webView.load(navigationAction.request)
        }
        return nil
    }
}

标签: swiftwkwebviewios14

解决方案


这不是最终的解决方案,但它以某种方式起作用。感谢WKWebView 没有打开 SOME target="_blank" 链接(5 岁的黑客)

很明显,在撰写本文时,WKWebView 在解析 href 标签的 _blank 目标属性时存在一些“未知”错误。

这个想法是在运行时“破解”加载的 html 代码并将所有 _blank 值替换为 _self。这将强制 WKWebView 将 _blank 链接加载到自身中。

func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
    let jsCode = "var allLinks = document.getElementsByTagName('a');if (allLinks) { var i;for (i=0; i<allLinks.length; i++) {var link = allLinks[i];var target = link.getAttribute('target');if (target && target == '_blank') {link.setAttribute('target','_self');} } }"
    webView.evaluateJavaScript(jsCode, completionHandler: nil)
}

推荐阅读