WKWebView didn't finish loading, when didFinishNavigation is called - Bug in WKWebView?

    For those still looking for an answer to this, the marked answer is BS, he just forced his way into getting it accepted.
   "loading" and webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) both do the same thing, indicate if the main resource is loaded. Now that does not mean the entire webpage/website is loaded, because it really depends on the implementation of the website. If it needs to load scripts and resources (images, fonts etc) to make itself visible, you'll still see nothing after the navigation is completed, because the network calls made by the website are not tracked by the webview, only the navigation is tracked, so it wouldn't really know when the website loaded completely.


WKWebView doesn't use delegation to let you know when content loading is complete (that's why you can't find any delegate method that suits your purpose). The way to know whether a WKWebView is still loading is to use KVO (key-value observing) to watch its loading property. In this way, you receive a notification when loading changes from true to false.

Here's a looping animated gif showing what happens when I test this. I load a web view and respond to its loading property through KVO to take a snapshot. The upper view is the web view; the lower (squashed) view is the snapshot. As you can see, the snapshot does capture the loaded content:

enter image description here

[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
    if (self->_webKitView.isLoading == true) {
        NSLog(@"Still loading...");
    }else {
        NSLog(@"Finished loading...");
        [timer invalidate];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self->_activityIndicator stopAnimating];
        });
    }
}];

Here is how I solved it:

class Myweb: WKWebView {

    func setupWebView(link: String) {
        let url = NSURL(string: link)
        let request = NSURLRequest(URL: url!)
        loadRequest(request)
        addObserver(self, forKeyPath: "loading", options: .New, context: nil)
    }

    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        guard let _ = object as? WKWebView else { return }
        guard let keyPath = keyPath else { return }
        guard let change = change else { return }
        switch keyPath {
        case "loading":
            if let val = change[NSKeyValueChangeNewKey] as? Bool {
                if val {
                } else {
                    print(self.loading)
                    //do something!
                }
            }
        default:break
        }
    }

    deinit {
        removeObserver(self, forKeyPath: "loading")
    }
}

Update Swift 3.1

override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    guard let _ = object as? WKWebView else { return }
    guard let keyPath = keyPath else { return }
    guard let change = change else { return }

    switch keyPath {
    case "loading":
        if let val = change[NSKeyValueChangeKey.newKey] as? Bool {
            //do something!
        }
    default:
        break
    }
}