我使用 UIWebView
从 webLink
和 UIWebViewDelegate
加载网页来控制错误状态:
I use UIWebView
to load web from a webLink
and UIWebViewDelegate
to control error state:
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:webLink]]];
- (void)webViewDidStartLoad:(UIWebView *)webView{
NSLog(@"START LOAD");
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSLog(@"FINISH LOAD");
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(@"ERROR : %@",error);
}
但是当 webLink
没有找到时,它不去 didFailLoadWithError
,它去 startLoad
和 didFinishLoad
.找不到webLink
的情况怎么办?请帮忙!
But when webLink
not found, it NOT go to didFailLoadWithError
, it go to startLoad
and didFinishLoad
. How to go the situation when webLink
not found?
Please help!
很遗憾,UIWebView
不会将 404(或类似代码)视为错误,因为收到了 HTML 响应.更糟糕的是,UIWebView
不会为我们捕获响应代码,因此您必须通过 NSURLConnection
手动执行此操作.这是处理它的一种方法:
Unfortunately, 404 (or similar codes) aren't considered errors by UIWebView
, because a HTML response was received. Worse, the UIWebView
doesn't capture response codes for us, so you have to do that manually, via NSURLConnection
. Here's one way to deal with it:
@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
{
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);
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode < 200 || statusCode >= 300) {
NSLog(@"%s request to %@ failed with statusCode=%d", __FUNCTION__, response.URL.absoluteString, statusCode);
} else {
self.validatedRequest = YES;
[self.webView loadRequest:connection.originalRequest];
}
}
[connection cancel];
}
@end
注意,在我的实现中,我不仅要检查状态代码,还要检查重定向(您可能想要也可能不想这样做).我这样做是因为一些 ISP 拦截了 HTTP 请求,如果找不到目标站点,则将您重定向到他们自己的搜索网页(知道我的 ISP 正在检查我搜索的每个网站,我认为这有点令人毛骨悚然).如果你正在处理通过 wifi 连接的 iPhone,你必须处理这些变幻莫测的问题.
Note, in my implementation, I'm not only checking for status codes, but I'm also checking for redirects (which you may or may not want to do). I do this because some ISP's intercept HTTP requests, and if the destination site is not found, redirect you to their own search web page (which I think is a bit creepy knowing that my ISP is checking out every web site I search for). And if you're dealing with iPhones that are connecting via wifi, you have to deal with these vagaries.
因此,例如,我上面的代码正在搜索http://www.applecom/pages"(其中我故意省略了.com"的句点,应该无法通过 DNS 查找),但我的 ISP Verizon 拦截了请求并通过 HTTP 连接重定向到他们自己的搜索页面因此,我的应用正在报告:
So, for example, my code above is searching for "http://www.applecom/pages" (in which I deliberately omitted the period of ".com", which should fail a DNS lookup), but for which my ISP, Verizon, intercepted the request and redirected by HTTP connection to their own search page and as such, my app is reporting:
2013-01-21 23:14:21.896 webtest[24198:c07] -[ViewController connection:didReceiveResponse:] 你是从 http://www.applecom/pages 到 http://search.dnsassist.verizon.net/assist.php?url=www.applecom
2013-01-21 23:14:21.896 webtest[24198:c07] -[ViewController connection:didReceiveResponse:] you were redirected from http://www.applecom/pages to http://search.dnsassist.verizon.net/assist.php?url=www.applecom
您可能需要考虑哪些类型的重定向是可接受的(例如,如果您转到www.adobephotoshop.com",它会将您重定向到www.adobe.com")以及哪些类型不可接受(例如,如果我访问www.applecom",它会将我重定向到search.dnsassist.verizon.net".我可能会担心一个相当狭窄的问题(由于我的 ISP 而影响到我),但这是值得考虑的事情.
You might want to think about what sort of redirects are acceptable (e.g., if you go to "www.adobephotoshop.com" and it redirects you to "www.adobe.com") and what sorts aren't (e.g., if I go to "www.applecom" and it redirects me to "search.dnsassist.verizon.net". I may be worrying about a fairly narrow problem (which affects me because of my ISP), but it's something to contemplate.
这篇关于找不到 webLink 时,UIWebView 不会去 didFailLoadWithError 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!