Web View Did Start Provisional Navigation not Called

Using WKWebView in my app and everything works fine until user is going to 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 or any other page on this site the delegate methods didStartProvisionalNavigation and didCommitNavigation not called.

Need these methods in order to detect the start of a navigation. decidePolicyForNavigationAction is called at the very beginning however it is called multiple times and I feel that using this method is not a perfect solution.

Question is: what can I do in such a situation. What so especial can be at that site what doesn’t make WKWebView call its delegate methods and what may be a reliable solution in this case

This Post Has One Comment

  1. No Fault

    I do not know very well web development, but it seems to me that the problem with JavaScript of the money.cnn.com site. It seems that the transitions between the site pages and their loading is carried out with help of JavaScript. That JavaScript conflict with native WKWebView handlers.

    But! You can inject your own JavaScript with handler at the beginning of the page. And when the page begins to open, the script will work first.

    Details
    Xcode Version 10.2.1 (10E1001), Swift 5
    Full example code
    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
    add in your Info.plist transport security setting

    NSAppTransportSecurity

    NSAllowsArbitraryLoads

Leave a Reply