0

I've searched and haven't found a solution to this, so hopefully someone can help.

I have a UIWebView that is called when a user presses a button. Everything works great, unless you account for behavior when the phone is without a data connection.

When attempting to open the UIWebView for the first time with the phone on airplane mode or without a data connection:

  • UIWebView starts to load
  • Fails to load

Once the UIWebView is allocated and fails to load for the first time, hitting a refresh button linked to an IBAction (that calls [webView reload]) causes:

  • Regardless of whether or not the phone has a data connection after the initial load fails, the refresh IBAction is called, but my NSLogs tell me neither webViewDidStartLoad, webViewDidFinishLoad, nor webView…didFailLoadWithError are called.

If I leave the app running and turn on a data connection to the device (e.g. turn off airplane mode,) then go back to my app and hit the refresh button, [webView reload] is called, but webViewDidStartLoad (and thus webViewDidFinishLoad) is not called.

Here's the relevant code:

To bring up the webView:

-(IBAction)loadWebView {

    webView = [[UIWebView alloc] init];
    webView.scalesPageToFit = YES;
    [webView setDelegate:self];

    NSString *urlAddress = @"http://google.com";
    NSURL *url = [NSURL URLWithString:urlAddress];
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

    [webView loadRequest:requestObj];

}

Reload:

  -(IBAction)reloadWebView{
    [webView reload];
    NSLog(@"RELOAD");
}

webViewDidStart, DidFinish, didFailLoadWithError:

 - (void)webViewDidStartLoad:(UIWebView *)webView
{  
    NSLog(@"START LOAD");   
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
     NSLog(@"FINISH LOAD");    
}

- (void)webView:(UIWebView *) webView didFailLoadWithError:(NSError *)error 
{ 
       NSLog(@"DID FAIL");
}

Thoughts?

2 Answers2

2

A good way to check if you should even bother trying to load a webpage is with Reachability.

NetworkStatus currentStatus = [[Reachability reachabilityForInternetConnection] 
                               currentReachabilityStatus];

if(currentStatus == kReachableViaWWAN) // 3G

else if(currentStatus == kReachableViaWifi) // ...wifi

else if(currentStatus == kNotReachable) // no connection currently possible

If you don't even start the webView loading when no connection is possible, you can probably avoid this scenario altogether.

A fix for the odd behaviour, though: In your refresh method try checking if it's loaded anything at all yet, and if not then call loadRequest:requestObj there. For example:

- (IBAction)reloadWebView {
    if(webView.request != nil)
        [webView reload];
    else {
        // reconstruct requestObj here, or use a class member
        [webView loadRequest:requestObj];
    }

    NSLog(@"RELOAD");
}
Natan R.
  • 5,141
  • 1
  • 31
  • 48
  • darvids0n, good point about initially relying on Reachability rather than doing it on my own. I was aware of the class, but wanted to see if it could be done easily on my own. Either way, using Reachability is definitely the way to go, if only because UIWebView isn't what I think a lot of us might want it to be. Many thanks! –  Sep 02 '11 at 06:35
1

I did encounter the same problem:

  1. Open my UIWebView for the first time with the phone on airplane mode or without a data connection, the following methods were called in turn:
    • -webView:shouldStartLoadWithRequest:navigationType:
    • -webViewDidStartLoad:
    • -webView:didFailLoadWithError
  2. Then, I tapped refresh button, that's to say, I called UIWebView's -reload method, no delegate method was called, so I even couldn't get a timeout notification.

My solution is:

  • Check network reachability status before load or reload requests, many thanks to @darvids0n's great advice(But I found out the request is not nil when reload after the request failed for the 1st time).
  • Use loadRequest: to reload the current URL instead of reload.
  • Implement my own timeout mechanism, such as, 20s after reload/load request, if no delegate methods were called, I take it as a timeout, and cancel requests and loadingHUD animation.

Some other similar issues: