我想在收到 HTTP 错误 404 等时通知用户。我怎样才能检测到呢?我已经尝试实施
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
但是当我收到 404 错误时不会调用它。
我想在收到 HTTP 错误 404 等时通知用户。我怎样才能检测到呢?我已经尝试实施
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
但是当我收到 404 错误时不会调用它。
我的实施灵感来自 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
}
}
它管理 HTTP 客户端错误 (4xx) 和 HTTP 服务器错误 (5xx)。
请注意,如果响应未缓存,则cachedResponseForRequest
返回,在这种情况下分配为 0,并且响应被认为是无错误的。nil
statusCode
您可以在此处捕获 URLRequest:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
并将请求交给代表并返回没有。然后在收到的来自NSURLConnection
取消连接的响应调用中,如果一切正常(检查响应)在 web 视图中再次加载 urlrequest。再次加载 urlrequest 时,请确保在上述调用中返回 YES。
不是很优雅,但它可能会起作用。
NSURLConnection 是您正在寻找的类,我认为这不能直接在 UIWebView 中完成。
您可以使用同步方法
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
或异步的。这些更难设置,因为您必须将获得的所有数据位附加到 1 NSData 中,但最终结果是相同的。
无论您使用的是同步还是异步方法:
如果你得到一个 NSError* 对象,那么就有一个 COMMS 错误。如其他响应中所述,这不是 HTTP 状态代码,而是通信问题。
如果连接成功,你会得到一个 NSURLResponse 和 NSData。重要的是 HTTP 请求的 NSURLResponse 实际上是 NSHTTPURLResponse 子类!
然后您必须检查响应以查看错误代码是什么。试试这个(_responseInfo
你的 NSURLResponse 对象在哪里):
NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;
responseInfo 应该始终是 HTTP 请求的 NSHTTPURLResponse ......但是为了以防万一,您最好在此处设置一个断言。
如果 statusCode 成功(即 200),那么您的 NSData 对象应该包含响应的数据(无论是什么)。如果状态码指示错误,则 NSData 可能包含来自服务器的错误的文本描述。
注意。我真的不建议为错误消息解析 NSData 对象。这就是 HTTP 'statusCode' 的用途!
UIWebView 不提供任何功能来获取它加载的请求的 HTTP 状态代码。一种解决方法是使用 UIWebViewDelegate 方法拦截 UIWebView 的请求加载过程,并使用 NSURLConnection 检测服务器如何响应该请求(如上所述)。然后,您可以采取适合情况的适当措施。
并且您不需要在收到响应后继续加载请求。学习 HTTP 状态码后,您可以在- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response方法中取消连接。这样可以防止连接加载任何不必要的响应数据。然后您可以再次在 UIWebView 中加载请求或根据 HTTP 状态代码等向用户显示适当的错误消息。
您误解了 -didFailLoadWithError 的用途。从技术上讲,请求成功了。它能够访问服务器并发现您请求的文件不存在(即 404)。例如,如果服务器不存在,将调用 -didFailLoadWithError 方法。您的服务器存在。文件没有。Web 视图不会解释内容中的错误。UIWebViewDelegate Apple Docs 中的 -didFailLoadWithError 的目的是:
如果 Web 视图无法加载内容,则发送。
来自关于HTTP 404的维基百科文章:
404 或 Not Found 错误消息是一个 HTTP 标准响应代码,表示客户端能够与服务器通信,但服务器找不到请求的内容。404 错误不应与“找不到服务器”或类似错误相混淆,在这些错误中,根本无法连接到目标服务器。
很有可能您必须解析 404 的响应文本,您可以使用 NSURLConnection/NSURLRequest 组合而不是 Web 视图来获得该响应文本。
此致,
我是 iOS 和 Swift 开发的新手,也需要找到一种方法来实现这一点,使用 WKWebView(而不是 UI)。我很幸运能在这个网站上运行,它给了我以下答案,非常适合我的需求。它可能会帮助正在寻找与我相同的答案的路人。
使用这个函数(来自 WKNavigationDelegate):
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)
您可以根据 HTTP 响应创建自定义响应,如下所示:
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
// get the statuscode
guard let statusCode = (navigationResponse.response as? HTTPURLResponse)?.statusCode
else {
decisionHandler(.allow)
return
}
// respond or pass-through however you like
switch statusCode {
case 400..<500:
webView.loadHTMLString("<html><body><h1>You shall not pass!</h1></body></html>", baseURL: nil)
case 500..<600:
webView.loadHTMLString("<html><body><h1>Sorry, our fault.</h1></body></html>", baseURL: nil)
default:
print("all might be well")
}
decisionHandler(.allow)
}
在 webViewDidFinishLoad 中:
if ([[(NSHTTPURLResponse*)[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request] valueForHTTPHeaderField:@"Status"] intValue] == 404){
}
即使某些响应可能不会被缓存,您也可以考虑使用此解决方案而不是其他更复杂的解决方案。请注意,错误的 url 通常会被具有默认配置的系统缓存。
这是我对@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
}
}
}
我将以下代码用于我的解决方案
-(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”);
}