shrutim shrutim - 19 days ago 7
iOS Question

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

Goal: To take a screenshot of WKWebView after the website finished loading

Method employed:


  • Defined a WKWebView var in UIViewController

  • Created an extension method called screen capture() that takes image of WKWebView

  • Made my UIViewController to implement WKNavigationDelegate

  • Set the wkwebview.navigationDelegate = self ( in the UIViewController init)

  • Implemented the didFinishNavigation delegation func in UIViewcontroller to call screen capture extension method for WKWebView




func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
let img = webView.screenCapture()
}



Questions:


  • When I debug i simulator, I notice that the control reaches the didFinishNavigation() func even though the website has not yet rendered in the WKWebView

  • Correspondingly the image screenshot taken is a white blob.



What am I missing here? I looked at all possible delegate functions for WKWebView and nothing else seem to represent the completion of content loading in WKWebView. Would appreciate help on if there is a work around




Update: Adding screenshot code that I am using to take a screenshot for web view

class func captureEntireUIWebViewImage(webView: WKWebView) -> UIImage? {

var webViewFrame = webView.scrollView.frame
if (webView.scrollView.contentSize != CGSize(width: 0,height: 0)){
webView.scrollView.frame = CGRectMake(webViewFrame.origin.x, webViewFrame.origin.y, webView.scrollView.contentSize.width, webView.scrollView.contentSize.height)

UIGraphicsBeginImageContextWithOptions(webView.scrollView.contentSize, webView.scrollView.opaque, 0)
webView.scrollView.layer.renderInContext(UIGraphicsGetCurrentContext())
var image:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

webView.scrollView.frame = webViewFrame
return image
}

return nil
}

Answer

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