Has anyone found that UIWebView fails for some URLS?
Question: I have been working on an iPhone App for a couple of weeks now and one of the
earlier features I added was a _UIWebView_ that loaded context sensitive
Wikipedia page topics. This was pretty trivial to implement and has been
working fine for some time.

Today, I found that functionality had unexpectedly stopped working. I had been
fiddling around at the perimeter of that piece of code and initially assumed
that I had broken something.

I checked all the obvious places, my urls, was the _UIWebView_ still hooked up
in the XIB etc. I didn't find any issues.

Investigating further, I stuck some error handling on my _UIWebViewDelegate_
*didFailLoadWithError* and found I was getting a -999 error:

> **NSURLErrorCancelled**
>
> Returned when an asynchronous load is canceled.
>
> A Web Kit framework delegate will receive this error when it performs a
> cancel operation on a loading resource. Note that an NSURLConnection or
> NSURLDownload delegate will not receive this error if the download is
> canceled.

So this sounds like making a new request (or cancelling) before the original
one has finished. I check my code for anything like this and come up empty.

So I went into my usual downward spiral of paranoia and assumed that Wikipedia
was blocking requests based on UAgent or something and went on something of
wild goose chase attempting to spoof my way back to a happy place. These
attempts were not successful and eventually sanity prevailed. I created a
simple python script to mimic the HTTP request I was making from my APP in the
simulator, to see what Wikipedia was sending back:

    
    
    string = "GET /wiki/Franklin_D._Roosevelt HTTP/1.1\r\nHost: en.wikipedia.org\r\nUser-Agent: test\r\nReferer: http://en.wikipedia.org/wiki/Franklin_D._Roosevelt\r\nAccept: */*\r\nAccept-Language: en-us\r\n_Accept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n"
    import socket
    s = socket.socket()
    s.connect(("en.wikipedia.org",80))
    s.send(string)
    x = s.recv (1000)
    while (x):
        print x
        x = s.recv (1000)
    

So I run this guy and discover that Wikipedia is very kindly returning my data
promptly and completely. So what is going on?

Chinks started to appear in my every present, paranoid armour "It's always my
fault" and I decide to check out if other iPhone apps can view these URLs. I
post a [tweet](http://twitter.com/redbluething/status/4906373854) with an
ironically amusing (I am easily amused) URL and check out if Tweetie can view
the URL. It can't.

A friend tries it out in Twitterific. Same problem. Works fine in Safari and
the Wikipedia App, but it seems like iPhone apps using a bog standard
_UIWebView_ are having problems with Wikipedia pages.

Just to be completely certain there are no other variables, I created a
[simple test app](http://www.cannonade.net/pics/UIWebViewTest.zip) with just a
UIWebView that loads up <http://en.wikipedia.com>, it fails with the same
error (added that code at the end).

So what do you guys think? Is this just a _UIWebView_ bug? Any Apple gronks
out there know what is going on here?

Have I missed something completely obvious and I am once again sitting on the
train to work without my pants on?

Looking forward to hearing what you think. Keep in mind, this was working fine
yesterday.

**Debrief** (or maybe Post Mortem is more appropriate):

Thanks [Duncan](http://stackoverflow.com/users/75656/duncanwilcox) for the
solution and a pretty clear description of what is going on here.

Looks like the reason I originally saw the error, when I wasn't implementing
the _didFailLoadWithError_ delegate method at all, was that the default
behavior for that method is apparently to clear the _UIWebView_ and
consequently kill the request. When I added my implementation to find out what
was going on, I stuck in some code to write the error to the view and, as
Duncan points out, this is what got me.

Seems like a pretty horrible solution to ignore -999 error codes in the
callback, but I am fine with duct tape.

I tried quite a few apps to test if this was a UIWebView problem (Tweetie,
Twitteriffic etc ...) and they all had the issue. It looks like this might be
a pretty common oversight for developers. Maybe Apple can clean this up in the
next version.

Other interesting point is that when I switched my URLs to use
<http://en.m.wikipedia.com> instead of <http://en.wikipedia.com>, the problem
went away.

    
    
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
        _webView = (UIWebView*)self.view;
        _webView.delegate = self;
    
        // load the url
    
        // FAIL
        //NSURL * newUrl = [[[NSURL alloc] initWithString:@"http://en.wikipedia.com"] autorelease];
    
        // OK
        NSURL * newUrl = [[[NSURL alloc] initWithString:@"http://www.stackoverflow.com"] autorelease];
    
        NSURLRequest * newUrlRequest = [NSURLRequest requestWithURL:newUrl];
        [_webView loadRequest:newUrlRequest];                                    
    }
    
    // delegate stuff
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)req navigationType:(UIWebViewNavigationType)navigationType { return YES; }
    - (void)webViewDidStartLoad:(UIWebView *)wv
        {
        // starting the load, show the activity indicator in the status bar
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    }
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        // finished loading, hide the activity indicator in the status bar
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    }
    
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    {
        NSURLErrorDomain
        // load error, hide the activity indicator in the status bar
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [_webView loadHTMLString:[[[NSString alloc] initWithFormat:@"Failed to load page %@", [error localizedDescription]] autorelease] baseURL:nil];
    }
    


Answer: Looks like there's an answer here:

<http://stackoverflow.com/questions/1024748/how-do-i-fix-nsurlerrordomain-
error-999-in-iphone-3-0-os>

which in turn refers to:

<http://www.iphonedevsdk.com/forum/iphone-sdk-development/6280-uiwebview-
didfailloadwitherror-how-get-errors-code-list.html>

Looks like you need a hack like this in the webView:didFailLoadWithError:
delegate:

    
    
    if ([error code] != NSURLErrorCancelled) {
        //show error alert, etc.
    }
    

In essence what's happening is the delegate is getting a "cancelled" (-999)
failure, that might be originated in javascript or perhaps even in a UIWebView
bug.

With your code the webview doesn't show anything at all because you're using
the very same UIWebView to display the error. If you had just NSLog'd the
error you would have seen a failure, but then the page would have loaded just
fine, giving you a hint that the failure is bogus.

