I would like to detect when a page load request give to a UIWebView has returned a status code in the 5xx or 4xx range.
I\'ve setup the delegate for the web view a
Hmmm... I'm not an iPhone developer, but....
Could you try creating an NSURLRequest with the URL you want to load? Then you could make the connection using NSURLConnection.
NSURLConnection has a delegate method
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
which will give the the response from the server. Please note that if you are making the connection over HTTP, the response will actually be of class NSHTTPURLResponse. The NSHTTPURLResponse can be used to get the status using the following instance method
- (NSInteger)statusCode
NSURLConnection has another delegate method
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
that can be used to get the data from the URL Connection. You could then manually load the data into your UIWebView using:
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
That seems like a ton of work, but it could be done. Hopefully someone else will come up with the easier way, though I don't see it.
I struggled with this for quite a while trying to find a good answer. The requirements that I was working under was that I needed to be able to determine the status of the FIRST page load, and any load after that I would assume that the user was clicking links which shouldn't be broken (not guaranteed, I know, but a lot better than the alternatives).
What I ended up doing was making the initial call myself via a NSURLConnection (synchronously), and then passing the data on to the UIWebView.
NSURL *googleURL = [NSURL URLWithString:@"http://www.google.com"];
NSURLRequest *googleRequest = [NSURLRequest requestWithURL:googleURL];
NSHTTPURLResponse *response;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:googleRequest
returningResponse:&response
error:&error];
if ([response statusCode] >= 400 || error)
{
// handle error condition
} else {
[webView_ loadData:responseData MIMEType:[response MIMEType]
textEncodingName:[response textEncodingName]
baseURL:[response URL]];
[self setView:webView_];
}
If you desire to get the information for every request, you could simply use the method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
to intercept all requests and make them yourself. You would have to have some kind of request management technique, because when you call the loadData on the UIWebView, it will invoke the shouldStartLoadWithRequest callback, and you want to make sure you don't do an infinite loop of making the same request over and over.
Here is a nice example where they use a combination of creating a NSURLConnection for the first loading, and the UIWebView for the next pages:
http://www.ardalahmet.com/2011/08/18/how-to-detect-and-handle-http-status-codes-in-uiwebviews/
Basically this is the main trick, using the YES/NO return value of shouldStartLoadRequest:
- (BOOL) webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if (_sessionChecked) {
// session already checked.
return YES;
}
// will check session.
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
if (conn == nil) {
NSLog(@"cannot create connection");
}
return NO;
}
This should get you going without using synchronous requests, especially combined with Jeff's answer.