20

There is a remote Javscript asset tag on a local HTML page I'm navigating to via WkWebView that never finishes downloading (in both the case that the iOS device is not connected to the internet, or the device's internet is too slow).

Unfortunately, the WKWebView never aborts trying to download this asset nor does it ever move on to my WKNavigationDelegate (i.e. neither -webView:didFailNavigation:withError: nor -webView:didFinishNavigation: neither are called), so users are stuck with a blank HTML page that never fully resolves and never errors out.

Thankfully in some scenarios I've debugged via the Safari remote iOS Javascript debugger, I've noticed we get the error Failed to load resource: The Internet connection appears to be offline logged to the console, but in others (like certain devices in Airplane Mode) the WKWebView never seems to timeout with this error or give up, so no WKNavigationDelegate callbacks get fired.

You can reproduce this scenario on your own by using the iOS 8.2 simulator with any WKWebView iOS application, navigate to any locally served HTML file, then add a script tag with any remote URL, then throttle your Internet connection to "100% Loss" using Apple's Network Link Conditioner.

What would be the best way to force a WkWebView to timeout/return via an error or success callback to its WKNavigationDelegate?

depthfirstdesigner
  • 3,033
  • 4
  • 29
  • 48

2 Answers2

23

Try:

WKNavigationDelegate

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error

You can check the error, usually you will have an error.code -1009:

Check this list: Error Codes

shim
  • 7,170
  • 10
  • 62
  • 95
Gabriel.Massana
  • 7,917
  • 6
  • 56
  • 79
  • 15
    -1 This method won't be called for a very long time and therefore not an answer. I've watched one minute pass before `-webView:: didFinishNavigation:` is called. The real OP question is in the last paragraph. – David Dec 29 '16 at 18:15
  • 1
    Fails for me almost instantly while in airplane mode; upvoted. – Sea Coast of Tibet Feb 07 '17 at 15:01
  • 1
    This returns an error immediately if there is no network connection – Lee Probert Jun 19 '17 at 11:32
  • 1
    In Swift 3 this now is `func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {` and Error has no member `.code`. – Tom Spee Aug 03 '17 at 15:18
  • I assume _code is a private API and you should not use it. – Lord Zsolt May 08 '18 at 13:15
  • 3
    I turned my iPhone to flight mode and tested, but didFailProvisionalNavigation won't be called. – Jia Xiao Jun 22 '18 at 10:03
-1

I think you will have to do this in your HTML page. You can include a small JavaScript there that runs a timer and checks if your remote script has loaded or not.

If it has not loaded then the JavaScript can show an error in the page directly or notify your application through a script message handler.

(I don't think HTML has an API that a page can use to find out about content loading errors. There are some hints about that on Verify External Script Is Loaded)

Community
  • 1
  • 1
Stefan Arentz
  • 31,710
  • 8
  • 65
  • 87
  • How do I check in Javascript to see if a remote script HTML tag has finished loading? The remote script runs everything in an immediately invoked function, so there's no global variables I can check for the existence of. – depthfirstdesigner Mar 12 '15 at 22:30