@interface ViewController () <UIWebViewDelegate, NSURLConnectionDataDelegate> @property (nonatomic) BOOL validatedRequest; @property (nonatomic, strong) NSURL *originalUrl; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // since `shouldStartLoadWithRequest` only validates when a user clicks on a link, we'll bypass that // here and go right to the `NSURLConnection`, which will validate the request, and if good, it will // load the web view for us. self.originalUrl = [NSURL URLWithString:@"http://www.stackoverflow.com"]; NSURLRequest *request = [NSURLRequest requestWithURL:self.originalUrl]; [NSURLConnection connectionWithRequest:request delegate:self]; } #pragma mark - UIWebViewDelegate // you will see this called for 404 errors - (void)webViewDidFinishLoad:(UIWebView *)webView { self.validatedRequest = NO; // reset this for the next link the user clicks on } // you will not see this called for 404 errors - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSLog(@"%s error=%@", __FUNCTION__, error); } // this is where you could, intercept HTML requests and route them through // NSURLConnection, to see if the server responds successfully. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // we're only validating links we click on; if we validated that successfully, though, let's just go open it // nb: we're only validating links we click on because some sites initiate additional html requests of // their own, and don't want to get involved in mediating each and every server request; we're only // going to concern ourselves with those links the user clicks on. if (self.validatedRequest || navigationType != UIWebViewNavigationTypeLinkClicked) return YES; // if user clicked on a link and we haven't validated it yet, let's do so self.originalUrl = request.URL; [NSURLConnection connectionWithRequest:request delegate:self]; // and if we're validating, don't bother to have the web view load it yet ... // the `didReceiveResponse` will do that for us once the connection has been validated return NO; } #pragma mark - NSURLConnectionDataDelegate method // This code inspired by http://www.ardalahmet.com/2011/08/18/how-to-detect-and-handle-http-status-codes-in-uiwebviews/ // Given that some ISPs do redirects that one might otherwise prefer to see handled as errors, I'm also checking // to see if the original URL's host matches the response's URL. This logic may be too restrictive (some valid redirects // will be rejected, such as www.adobephotoshop.com which redirects you to www.adobe.com), but does capture the ISP // redirect problem I am concerned about. - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; NSString *originalUrlHostName = self.originalUrl.host; NSString *responseUrlHostName = response.URL.host; NSRange originalInResponse = [responseUrlHostName rangeOfString:originalUrlHostName]; // handle where we went to "apple.com" and got redirected to "www.apple.com" NSRange responseInOriginal = [originalUrlHostName rangeOfString:responseUrlHostName]; // handle where we went to "www.stackoverflow.com" and got redirected to "stackoverflow.com" if (originalInResponse.location == NSNotFound && responseInOriginal.location == NSNotFound) { NSLog(@"%s you were redirected from %@ to %@", __FUNCTION__, self.originalUrl.absoluteString, response.URL.absoluteString); } else if (httpResponse.statusCode < 200 || httpResponse.statusCode >= 300) { NSLog(@"%s request to %@ failed with statusCode=%d", __FUNCTION__, response.URL.absoluteString, httpResponse.statusCode); } else { [connection cancel]; self.validatedRequest = YES; [self.webView loadRequest:connection.originalRequest]; return; } [connection cancel]; } @end
how-to-detect-and-handle-http-status-codes-in-uiwebviews
猜你喜欢
转载自zani.iteye.com/blog/2047131
今日推荐
周排行