UIWebView didFinishLoading fires multiple times

IphoneIosObjective CXcodeUiwebview

Iphone Problem Overview


I have some code that needs to run after the a UIWebView finishes loading a document. For that I've set the UIWebView's delegate to my controller, and implemented the webViewDidFinishLoading method.

This gets called multiple times, depending on the type of page to load. I'm not sure if it's because of ajax requests, requests for images, or maybe even iframes.

Is there a way to tell that the main request has finished, meaning the HTML is completely loaded?

Or perhaps delay my code from firing until all of those events are done firing?

Iphone Solutions


Solution 1 - Iphone

You can do something like this to check when loading is finished. Because you can have a lot of content on the same page you need it.

- (void)webViewDidFinishLoad:(UIWebView *)webview  {
    if (webview.isLoading)
        return;
    // do some work
}

Solution 2 - Iphone

It could be enlightening (if you haven't gone this far yet) to NSLog a trace of load starts and finishes.

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
       NSLog(@"Loading: %@", [request URL]);
       return YES;
    }
    
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
       NSLog(@"didFinish: %@; stillLoading: %@", [[webView request]URL],
            (webView.loading?@"YES":@"NO"));
    }
    
    
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
       NSLog(@"didFail: %@; stillLoading: %@", [[webView request]URL],
            (webView.loading?@"YES":@"NO"));
    }

I just watched the calls to all three in one of my projects which loads a help page from my bundle and contains embedded resources (external css, YUI!, images). The only request that comes through is the initial page load, shouldStartLoadWithRequest isn't called for any of the dependencies. So it is curious why your didFinishLoad is called multiple times.

Perhaps what you're seeing is due to redirects, or as mentioned, ajax calls within a loaded page. But you at least should be able balance calls to shouldStartLoad and either of the other two delegate functions and be able to determine when the loading is finished.

Solution 3 - Iphone

Check this one it so simply and easy way to achieve no need to write too much code:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
        if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) {
            // UIWebView object has fully loaded.
        }
    }

Solution 4 - Iphone

This question is already solved, but I see it lacks an answer that actually explains why multiple calls to webViewDidFinishLoad are actually expected behavior

The aforementioned method is called every time the webview finishes loading a frame. From the UIWebViewDelegate protocol documentation:

> webViewDidFinishLoad:
> Sent after a web view finishes loading a frame.

In fact, this is also true for all the other methods that comprise the UIWebViewDelegate protocol.

Solution 5 - Iphone

Try this it will work fine

 -(void)webViewDidFinishLoad:(UIWebView *)webview  
    {
       if (webview.isLoading)
           return;
       else
       {
           // Use the code here which ever you need to run after webview loaded 
       }
    }

Solution 6 - Iphone

This happens because the callback method is called every time a frame is done loading. In order to prevent this set the "suppressesIncrementalRendering" property of the webview to true. this will prevent the webview from rendering until the entire data is loaded into the memory. This did the trick for me

Solution 7 - Iphone

I have notice something similar and it was a confusion: I have a UITabBarController, it seems to preload all ViewControllers linked to its tabs on launching the App (in spite of showing just first_Tab_ViewController), so when several tabs have ViewController with WebView their respective webViewDidFinishLoad are called and if I have copied pasted:

NSLog(@"size width %0.0f height %0.0f", fitingSize.width, fittingSize.height); 

in several, I get several output in console that appears to be a double calling when they really are single calling in two different UIWebViews.

Solution 8 - Iphone

You could check the loading and request properties in the webViewDidFinishLoad method

Solution 9 - Iphone

Possibly related to this issue is a property on UIWebView introduced in iOS6: suppressesIncrementalRendering.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBen ScheirmanView Question on Stackoverflow
Solution 1 - IphoneScott DensmoreView Answer on Stackoverflow
Solution 2 - IphonewkwView Answer on Stackoverflow
Solution 3 - IphoneVinod SinghView Answer on Stackoverflow
Solution 4 - IphoneCezarView Answer on Stackoverflow
Solution 5 - IphoneYogeesh H TView Answer on Stackoverflow
Solution 6 - IphoneViswanth ChadalawadaView Answer on Stackoverflow
Solution 7 - IphoneLuisView Answer on Stackoverflow
Solution 8 - IphonenicoView Answer on Stackoverflow
Solution 9 - IphoneAlfie HanssenView Answer on Stackoverflow