Empty or incorrect URL with webViewDidStartLoad

Posted by on Aug 9, 2011 in iOS, iPad, iPhone, Mobile Applications | No Comments

If you’re using a UIWebView in your iPhone or iPad app and you want to execute some code when a page starts loading you’ll likely turn to the webViewDidStartLoad: method in UIWebViewDelegate. However, you may have surprisingly unpredictable results. For example, the following code won’t work as expected:

- (void)webViewDidStartLoad:(UIWebView *)webView {
    if ([webView.request.URL hasPrefix:@"http://mywebsite.com"]) {
        // Show buttons specific to my site
    }
}

The issues you’ll run into are:

  1. On many web pages this method gets called more than once because of things like Google ads, iframes, etc. However, on simpler pages it only gets called once.
  2. When this delegate method is called the first time (and possibly the only time), webView.request.URL contains an empty string and not the URL of the page that’s about top load. However, if there are subsequent calls then you can get access to the URL. This makes for code that works with certain web pages but mysteriously fails on other web pages!

I resolved all of my issues by bailing on webViewDidStartLoad: and using the alternate delegate method webView:shouldStartLoadWithRequest:navigationType: which works as you’d expect. It’s only called once when a page is about to start loading and the request contains the actual URL that is about to load in the UIWebView:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if ([request.URL hasPrefix:@"http://mywebsite.com"]) {
        // Show buttons specific to my site
    }
}

Unfortunately, there’s no finished loading delegate method that’s guaranteed to only get called once. Like viewDidStartLoad:, viewDidFinishLoad: gets called multiple times, depending on the page.

Leave a Reply