如何检测和处理UIWebView中的HTTP错误代码?
我想告诉用户何时收到HTTP错误404等。 我如何检测? 我已经试图实现
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
但是当我收到404错误时不会调用它。
你可以在这里捕获URLRequest:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
并将请求交给委托,并返回no。 然后在从NSURLConnection
接收到的响应呼叫取消连接,如果一切正常(检查响应)在web视图中再次加载urlrequest。 再次加载urlrequest时,请确保在上述调用中返回YES。
不是很优雅,但它可能工作。
我的实现受到Radu Simionescu的回应的启发:
- (void)webViewDidFinishLoad:(UIWebView *)webView { NSCachedURLResponse *urlResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request]; NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) urlResponse.response; NSInteger statusCode = httpResponse.statusCode; if (statusCode > 399) { NSError *error = [NSError errorWithDomain:@"HTTP Error" code:httpResponse.statusCode userInfo:@{@"response":httpResponse}]; // Forward the error to webView:didFailLoadWithError: or other } else { // No HTTP error } }
它pipe理HTTP客户端错误(4xx)和HTTP服务器错误(5xx)。
请注意,如果响应没有被caching,则cachedResponseForRequest
返回nil
,在这种情况下, statusCode
被赋值为0,并且响应被认为是无误的。
UIWebView不提供任何获取它加载的请求的HTTP状态代码的function。 一种解决方法是使用UIWebViewDelegate方法拦截UIWebView的请求加载过程,并使用NSURLConnection来检测服务器如何响应该请求(如上所述)。 那么你可以采取适当的行动适合的情况。 本文将详细介绍演示项目的解决方法。
在收到回复后,您不需要继续加载请求。 学习HTTP状态码后,你可以直接取消– (void)连接中的连接:(NSURLConnection *)连接didReceiveResponse:(NSURLResponse *)响应方法。 这样可以防止连接加载任何不必要的响应数据。 然后,您可以再次在UIWebView中加载请求,或根据HTTP状态代码等向用户显示相应的错误消息。
这里是文章
这里是github上的演示项目
你错误地解释了-didFailLoadWithError的用途。 技术上,请求成功。 它能够击中服务器,并发现你要求的文件不存在(即404)。 例如,如果服务器不存在,则会调用-didFailLoadWithError方法。 你的服务器存在。 该文件没有。 networking视图不会解释内容中的错误。 UIWebViewDelegate Apple Docs中的-didFailLoadWithError的用途是:
如果Web视图未能加载内容,则发送。
从HTTP 404上的维基百科文章:
404或Not Found错误消息是HTTP标准响应代码,指示客户端能够与服务器进行通信,但服务器找不到请求的内容。 404错误不应与“未find服务器”或类似的错误相混淆,在这种错误中根本无法连接到目标服务器。
很有可能你必须parsing一个你可以用NSURLConnection / NSURLRequest组合而不是Web视图获得的404响应文本。
最好的祝福,
NSURLConnection是你正在寻找的类,我不认为这可以直接在UIWebView中完成。
您可以使用同步方法
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
或者是asynchronous的。 这些设置比较困难,因为您必须将所有的数据添加到1个NSData中,但最终的结果是一样的。
无论您使用“同步”还是“asynchronous”方法:
如果你得到一个NSError *对象,那么就会出现COMMS错误。 正如其他答复中所述,这不是一个HTTP状态码,而是一个通信问题。
如果连接成功,你会得到一个NSURLResponse和NSData。 重要的是,HTTP请求的NSURLResponse实际上是NSHTTPURLResponse子类!
然后,您必须检查响应,看看错误代码是什么。 试试这个(其中_responseInfo
是你的NSURLResponse对象):
NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;
responseInfo应该总是一个NSHTTPURLResponse的HTTP请求…但你可能是聪明的有一个断言,以防万一。
如果statusCode是成功的(即200),那么你的NSData对象应该包含响应的数据(不pipe是什么)。 如果状态码指示错误,那么NSData可能包含来自服务器的错误的文本描述。
NB。 我真的不build议tyringparsingNSData对象的错误消息。 这就是HTTP'statusCode'的用途!
在webViewDidFinishLoad中:
if ([[(NSHTTPURLResponse*)[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request] valueForHTTPHeaderField:@"Status"] intValue] == 404){ }
您可能会考虑将此解决scheme放在其他更复杂的解决scheme上,即使某些响应可能无法caching。 请注意,错误的URL通常会被具有默认configuration的系统caching。
下面是@AxelGuilmin响应的快速3版本:
func webViewDidFinishLoad(_ webView: UIWebView) { guard let request = webView.request else { return } let cachedUrlResponse = URLCache.shared.cachedResponse(for: request) let httpUrlResponse = cachedUrlResponse?.response as? HTTPURLResponse if let statusCode = httpUrlResponse?.statusCode { if statusCode == 404 { // Handling 404 response } } }
我使用下面的代码为我的解决scheme
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{ NSLog(@"error :%@",error); NSString *strError = [NSString stringWithFormat:@"%@",error]; if ([strError rangeOfString:@"Code=-1005"].location == NSNotFound) { NSLog(@"string does not contain Code=-1005"); } else NSLog(@"string contains Code=-1005”);
}