Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIWebView - How to identify the "last" webViewDidFinishLoad message?

The webViewDidFinishLoad message seems to be sent each time any object in the page has been loaded. Is there a way to determine that all loading of content is done?

like image 249
chendral Avatar asked May 25 '09 23:05

chendral


6 Answers

I'm guessing that iframes cause the webViewDidStartLoad / webViewDidFinishLoad pair.

The [webView isLoading] check mentioned as an answer didn't work for me; it returned false even after the first of two webViewDidFinishLoad calls. Instead, I keep track of the loading as follows:

- (void)webViewDidStartLoad:(UIWebView *)webView {
  webViewLoads_++;
}


- (void)webViewDidFinishLoad:(UIWebView *)webView {
  webViewLoads_--;

  if (webViewLoads_ > 0) {
    return;
  }

  …
}

- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error {
  webViewLoads_--;
}

(Note this will only work if the start / finished pairs don't come serially, but in my experience so far that hasn't happened.)

like image 179
Fiona Hopkins Avatar answered Nov 05 '22 10:11

Fiona Hopkins


Check this one, it will definitely work for you:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if ([[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"]) {
        // UIWebView object has fully loaded.
    }
}
like image 39
Vinod Singh Avatar answered Nov 05 '22 11:11

Vinod Singh


Interesting, I wouldn't have thought it would work like that. Although I'm sure there are other ways to do it (is there a way to extract the URL from the webViewDidFinishLoad message so that you can see which one is the main page finishing loading?), the main thing I can think of is using the estimatedProgress to check the progress of the page and fire off whatever you want to do when it's 100% finished loading, which is what I do in my app. Google "iphone webview estimatedprogress" and click the first link for a guide I wrote on how to do this.

Update:

Please use phopkins' answer below instead of mine! Using private APIs in your apps is a bad idea and you will probably get rejected, and his solution is the right one.

like image 9
AriX Avatar answered Nov 05 '22 10:11

AriX


Another way to monitor load progress with less control is to observe the WebViewProgressEstimateChangedNotification, WebViewProgressFinishedNotification, and WebViewProgressStartedNotification notifications. For example, you could observe these notifications to implement a simple progress indicator in your application. You update the progress indicator by invoking the estimatedProgress method to get an estimate of the amount of content that is currently loaded.

from http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/WebKit/Classes/WebView_Class/Reference/Reference.html

like image 1
KarenAnne Avatar answered Nov 05 '22 12:11

KarenAnne


You can also use this short Category I wrote that adds blocks into UIWebView and also lets you choose between default UIWebView behavior (getting notified after each object load), or the "expected" behavior (getting notified only when the page has fully loaded).

https://github.com/freak4pc/UIWebView-Blocks

like image 1
Shai Mishali Avatar answered Nov 05 '22 10:11

Shai Mishali


I needed to capture a variable from the page which was not fully loaded yet.

This worked for me:

- (void) webViewDidFinishLoad:(UIWebView *)webView {
    NSString *valueID = [webView stringByEvaluatingJavaScriptFromString:@"document.valueID;"];

    if([valueID isEqualToString:@""]){
        [webView reload];
        return;
    }

    //page loaded
}
like image 1
Petr Avatar answered Nov 05 '22 10:11

Petr