views:

886

answers:

3

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?

A: 

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

nico
I've checked the Content-Type HTTP header and the URL and they don't give me any useful information.What information are you suggesting to look at?
Ben Scheirman
+1  A: 

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.loading)
        return;
    // dow some work
}
Scott Densmore
ok this sort of worked (and in fact much cleaner than the NSTimer abomination I had previously concocted).It does unfortunately get to the //do some work section more than once, most likely because there is a delay between requests.Any ideas on how to ensure that it only gets called once?
Ben Scheirman
When you say "delay between requests", are you making multiple requests with an NSUrl? You could use the request property of webview if you need to correlate the requests. If you want direct msg me on twitter and we can figure this out then update this post.
Scott Densmore
yeah, eventually that if(webview.loading) returns false, and I execute my code (show an alert, say). The alert box is shown twice, because apparently something else starts loading after the main request is finished... I'm not sure.
Ben Scheirman
+1  A: 

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]);
    }


    - (void)webViewDidFinishLoad:(UIWebView *)webView {
       NSLog(@"didFinish: %@; stillLoading:%@", [[webView request]URL],
            (webView.loading?@"NO":@"YES"));
    }


    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
       NSLog(@"didFail: %@; stillLoading:%@", [[webView request]URL],
            (webView.loading?@"NO":@"YES"));
    }

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.

wkw
This ultimately helped me figure it out. I was using my own webView ivar to determine the request URL, but that never changed. The webView passed into this method contained the actual current request URL and I could see all of the additional content loading (iframes, etc).Thanks for the help!
Ben Scheirman
Shouldn't it be (webView.loading?@"YES":@"NO")instead of (webView.loading?@"NO":@"YES")
Vibhor Goyal