0

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?

user1872384
  • 6,298
  • 9
  • 49
  • 87
  • you can refer to this post: https://stackoverflow.com/questions/36313253/how-to-check-if-wkwebview-finish-loading-in-objective-c – Madhur Jan 03 '18 at 07:58
  • yes I'm already using webView:didFinishNavigation: to detect. However, does it trigger after the base64 image is loaded or before? – user1872384 Jan 03 '18 at 07:59

1 Answers1

2

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.

trungduc
  • 11,323
  • 4
  • 29
  • 51
  • Hi @trungduc, it's a nice trick if the image frame is not loaded. In my case, the image frame is there (hence, the height of the webview is the same when the image is loaded and when it's not) just that the image is not loaded :( – user1872384 Jan 16 '18 at 09:02
  • Ok I got it. Can you show me the way you changed image? I think we just need to change javascript to be suitable with your problem. – trungduc Jan 16 '18 at 09:10
  • I'm just using a simple image tag, the data source is in base64 format as shown in the question. < img class="icon" src="data:image/png;base64,/9j/4AAQSkZJRgABAQEAlgCWAAD/7gAOQWRvYmUAZAAAAAAA/...> – user1872384 Jan 16 '18 at 09:17
  • So in case image isn't loaded, src will be empty. Is it right? – trungduc Jan 16 '18 at 09:23
  • It's hard to replicate the issue. Are you able to test it using a very large data source? Theoretically the source will be empty when the image is not loaded. – user1872384 Jan 16 '18 at 09:38
  • If src is empty in case image isn't loaded, my solution will work. You should download repo to check first. Try to remove src in my html string and you will know it work or not. – trungduc Jan 16 '18 at 09:44
  • Image is still missing after trying for a few times. Is it cause by WKWebview rendering issue? – user1872384 Jan 17 '18 at 10:28
  • I don't think it's `WKWebView` rendering issue. I think you should check the way you change image. – trungduc Jan 17 '18 at 10:35
  • removing the base64 image and replace with a file. . Not sure if this is what you meant... – user1872384 Jan 17 '18 at 10:56
  • `Image is still missing after trying for a few times`. Do you mean image doesn't appear or `didReceiveScriptMessage` didn't be called? – trungduc Jan 17 '18 at 11:07