20

我想在收到 HTTP 错误 404 等时通知用户。我怎样才能检测到呢?我已经尝试实施

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error

但是当我收到 404 错误时不会调用它。

4

9 回答 9

18

我的实施灵感来自 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,并且响应被认为是无错误的。nilstatusCode

于 2014-10-31T11:22:25.380 回答
8

您可以在此处捕获 URLRequest:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

并将请求交给代表并返回没有。然后在收到的来自NSURLConnection取消连接的响应调用中,如果一切正常(检查响应)在 web 视图中再次加载 urlrequest。再次加载 urlrequest 时,请确保在上述调用中返回 YES。

不是很优雅,但它可能会起作用。

于 2010-02-10T11:43:06.833 回答
8

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' 的用途!

于 2010-06-07T08:22:14.370 回答
8

UIWebView 不提供任何功能来获取它加载的请求的 HTTP 状态代码。一种解决方法是使用 UIWebViewDelegate 方法拦截 UIWebView 的请求加载过程,并使用 NSURLConnection 检测服务器如何响应该请求(如上所述)。然后,您可以采取适合情况的适当措施。

并且您不需要在收到响应后继续加载请求。学习 HTTP 状态码后,您可以在- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response方法中取消连接。这样可以防止连接加载任何不必要的响应数据。然后您可以再次在 UIWebView 中加载请求或根据 HTTP 状态代码等向用户显示适当的错误消息。

这是github上的演示项目

于 2011-08-19T00:27:25.863 回答
8

您误解了 -didFailLoadWithError 的用途。从技术上讲,请求成功了。它能够访问服务器并发现您请求的文件不存在(即 404)。例如,如果服务器不存在,将调用 -didFailLoadWithError 方法。您的服务器存在。文件没有。Web 视图不会解释内容中的错误。UIWebViewDelegate Apple Docs 中的 -didFailLoadWithError 的目的是:

如果 Web 视图无法加载内容,则发送。

来自关于HTTP 404的维基百科文章:

404 或 Not Found 错误消息是一个 HTTP 标准响应代码,表示客户端能够与服务器通信,但服务器找不到请求的内容。404 错误不应与“找不到服务器”或类似错误相混淆,在这些错误中,根本无法连接到目标服务器。

很有可能您必须解析 404 的响应文本,您可以使用 NSURLConnection/NSURLRequest 组合而不是 Web 视图来获得该响应文本。

此致,

于 2010-02-10T16:43:54.133 回答
4

我是 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)
}
于 2019-01-04T19:08:17.677 回答
2

在 webViewDidFinishLoad 中:

if ([[(NSHTTPURLResponse*)[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request] valueForHTTPHeaderField:@"Status"] intValue] == 404){
}

即使某些响应可能不会被缓存,您也可以考虑使用此解决方案而不是其他更复杂的解决方案。请注意,错误的 url 通常会被具有默认配置的系统缓存。

于 2014-03-27T13:47:26.567 回答
1

这是我对@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
            }
        }
    }
于 2017-04-27T11:24:14.873 回答
-1

我将以下代码用于我的解决方案

-(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”);

}

于 2014-11-10T09:49:41.710 回答