17
votes

I am trying to build a filter for a UIWebView and I am struggiling to detect when the UIWebView has completely finished loading. I have used the following two methods

– webView:shouldStartLoadWithRequest:navigationType:
– webViewDidFinishLoad:

but the issue is that these will be called multiple times when a page has frames and additional content to load.

What I need is to know when the view has completely loaded and there is no more content to fetch. Then when the content has loaded I can check to URL of the page against a list of approved URLS.

ANy ideas?

5
You could try putting a flag in shouldStartLoad, and check it in didFinishLoad after a second or two before calling all the loading done ... This should be relatively robust if everything on the page is intended to load as soon as you hit the page. Just an idea though; only content I've worked with all loaded in one go ...David Doyle
I've thought about that but didFinishLoad gets called a few times during a page load. I need to find out when the last call has finished loading.ORStudios
Is there ever more than a couple of seconds between one didFinishLoad and the next didStartLoad of the next one?David Doyle

5 Answers

34
votes

Use the UIWebViewDelegate protocol method webViewDidFinishLoad and webView's isLoading property

 - (void)webViewDidFinishLoad:(UIWebView *)webView
 {
    //Check here if still webview is loding the content
    if (webView.isLoading)
       return;

    //after code when webview finishes
    NSLog(@"Webview loding finished");
 }
2
votes

Swift 3 version:

func webViewDidFinishLoad(_ webView: UIWebView) {
    if webView.isLoading{
        return
    }
    print("Done loading")
}
1
votes

Try use:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)requestURL navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [requestURL URL];
NSLog(@"##### url = %@",[url absoluteString]); 
return YES;
}

don't forget to set your UIWebView Delegate

or add statement,

NSRange range = [[url absoluteString] rangeOfString:@"https://www.google.com"];
if (range.location != NSNotFound)
{}

hope to help you.

1
votes

It is true that the original question was posted many years ago. Recently I had to find a reliable solution to this issue.

Here is the solution that worked for me:

  1. Replaced UIWebView with WKWebWiew.
  2. Added 'evaluateJavaScript' code while handling the 'didFinishNavigation' delegate method.

The complete code is:

   - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
    [webView evaluateJavaScript:@"document.body.innerHTML" completionHandler:^(id result, NSError *error) {
        if (result != nil) {
            // Call your method here
        }
        if(error) {
            NSLog(@"evaluateJavaScript error : %@", error.localizedDescription);
        }
    }];
}
0
votes

If you aren't an owner of UIWebView and as a result you don't have an access to webViewDidFinishLoad but you have a reference to UIWebView you can use the next code

Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { (timer) in

    guard uiWebView.isLoading else {
        return
    }

    timer.invalidate()
    //Add your logic here

}