WKWeb 视图。 didStartProvisionalNavigation 未调用

WKWebView. didStartProvisionalNavigation not called

我在我的应用程序中使用 WKWebView,一切正常,直到用户转到 money.cnn.com. For the main page of this site everything is fine as well but when user leaves the main page and goes for example to http://money.cnn.com/2016/11/21/news/dubai-trump-golf-course-developer/index.html?iid=hp-toplead-intl 或该站点上的任何其他页面委托方法 didStartProvisionalNavigationdidCommitNavigation 未调用。但是我需要这些方法来检测导航的开始。 decidePolicyForNavigationAction一开始就被调用了,但是被调用了多次,我觉得使用这种方法并不是一个完美的解决方案。所以我的问题是:在这种情况下我能做什么?在那个站点上有什么特别之处是什么不能使 WKWebView 调用它的委托方法,在这种情况下什么可能是可靠的解决方案?谢谢

我不太了解网络开发,但在我看来,money.cnn.com 站点的 JavaScript 存在问题。似乎网站页面之间的转换及其加载是在 JavaScript 的帮助下完成的。 JavaScript 与本机 WKWebView 处理程序冲突。

但是!您可以在页面开头注入自己的 JavaScript with handler。当页面开始打开时,脚本将首先运行。

详情

  • Xcode 版本 10.2.1 (10E1001),Swift 5

完整示例代码

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler {

    private weak var webView: WKWebView?
    private lazy var scriptName = "GetUrl"

    override func viewDidLoad() {
        super.viewDidLoad()
        setupWebView()
        loadUrl(string: "http://money.cnn.com/2016/11/21/news/dubai-trump-golf-course-developer/index.html?iid=hp-toplead-intl")
    }

    func setupWebView() {
        let contentController = WKUserContentController();
        let script = "webkit.messageHandlers.\(scriptName).postMessage(document.URL)"
        let userScript = WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true)
        contentController.addUserScript(userScript)
        contentController.add(self, name: scriptName)

        let config = WKWebViewConfiguration()
        config.userContentController = contentController

        let webView = WKWebView(frame:  UIScreen.main.bounds, configuration: config)
        webView.navigationDelegate = self
        view.addSubview(webView)
        self.webView = webView
    }

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == scriptName {
            guard let url = message.body as? String else { return }
            if url.contains("http://money.cnn.com/") {
                print("!!! \(url)")
            } else {
                print("??? \(url)")
            }
        }
    }

    func loadUrl(string: String) {
        guard   let url = URL(string: string),
                let webView = self.webView else { return }
        webView.load(URLRequest(url: url))
    }
}

Info.plist

添加您的 Info.plist 传输安全设置

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

结果

更多

Call JavaScript function from native code in WKWebView

设置委托如下:

webView.navigationDelegate = self