user1872384
user1872384

Reputation: 7147

How to detect if an image in a html is fully loaded in WKWebView?

I'm loading a local html with a < img> tag e.g. :

< img class="icon" src="data:image/png;base64,/9j/4AAQSkZJRgABAQEAlgCWAAD/7gAOQWRvYmUAZAAAAAAA/...

However, how can I detect if the image is fully loaded? I'm using this to detect. However, it doesn't seem to work. Sometimes the image is loaded, sometimes it's not.

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    if (webView.isLoading) return;
    ..
    //proceed to load the second html
}

Update:

I've added a delay in the didFinishNavigation delegate and the image is loaded perfectly:

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
if (webView.isLoading) return;


double delayInSeconds = 3.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    NSLog(@"Do some work");

});

}

However, this is an interim solution. Is there a better solution?

Upvotes: 1

Views: 1440

Answers (1)

trungduc
trungduc

Reputation: 12154

My solution is using javascript code to check content's height of webView. If the height is bigger than or equal a number (it means that having something inside webView, it's the image), post a message to webView and use WKScriptMessageHandler to handle message in native code.

Example

Create javascript code. Check if content's height is bigger than 50, post message to check image is loaded.

NSString* source =
    [NSString stringWithFormat:
                  @"var sizeInterval = setInterval("
                   "function() {"
                   "var h = 0;"
                   "var children = document.body.children;"
                   "for (var c = 0; c < children.length; c++) {"
                   "h += children[c].offsetHeight;"
                   "}"
                   "if (h > 50) {"
                   "clearInterval(sizeInterval);"
                   "window.webkit.messageHandlers.%@.postMessage('loaded');"
                   "}"
                   "},"
                   "100);",
                  kContentLoadedMessage];

WKUserScript* script = [[WKUserScript alloc]
      initWithSource:source
       injectionTime:WKUserScriptInjectionTimeAtDocumentStart
    forMainFrameOnly:YES];

WKUserContentController* contentController =
    [[WKUserContentController alloc] init];
[contentController addUserScript:script];
[contentController addScriptMessageHandler:self name:kContentLoadedMessage];

WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = contentController;

YOUR_WK_WEB_VIEW =
    [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
// Add webView to a view and load html

Using WKScriptMessageHandler to handle message.

- (void)userContentController:(WKUserContentController*)userContentController
      didReceiveScriptMessage:(WKScriptMessage*)message {
  if ([message.name isEqualToString:kContentLoadedMessage]) {
    NSLog(@"Image was loaded");
  }
}

You can check my demo repo for more understanding.

Upvotes: 2

Related Questions