如何在UIWebView中检测和处理HTTP错误代码?

时间:2010-02-10 11:30:24

标签: ios objective-c iphone uiwebview nserror

我想在收到HTTP错误404等时通知用户。我怎么能检测出来? 我已经尝试过实施

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

但是当我收到404错误时它没有被调用。

9 个答案:

答案 0 :(得分:19)

我的实施灵感来自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将返回nil,在这种情况下,statusCode被指定为0,并且响应被视为无错误。

答案 1 :(得分:8)

UIWebView不提供任何获取其加载的请求的HTTP状态代码的功能。一种解决方法是使用UIWebViewDelegate方法拦截UIWebView的请求加载过程,并使用NSURLConnection检测服务器如何响应该请求(如上所述)。然后你可以采取适合这种情况的适当行动。 This article详细解释了演示项目的解决方法。

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

Here is the article

and here is the demo project on github

答案 2 :(得分:7)

您可以在此处捕获URLRequest:

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

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

不是很优雅,但它可能有用。

答案 3 :(得分:7)

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

  

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

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

  

404或Not Found错误消息是   HTTP标准响应代码   表明客户端能够   与服务器通信但是   服务器找不到的是什么   请求。 404错误不应该   与“未找到服务器”或   类似的错误,其中有一个连接   到目标服务器不能   制作完毕。

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

最诚挚的问候,

答案 4 :(得分:7)

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可能包含来自服务器的错误的文本描述。

NB。我真的不建议使用tyring来解析NSData对象的错误消息。这就是HTTP'statusCode'的用途!

答案 5 :(得分:2)

在webViewDidFinishLoad中:

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

您可以将此解决方案视为其他更复杂的解决方案,即使某些响应可能未被缓存。请注意,错误的URL通常会被具有默认配置的系统缓存。

答案 6 :(得分:2)

Heres是@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
            }
        }
    }

答案 7 :(得分:1)

我不熟悉iOS和Swift开发,因此需要找到一种方法来使用WKWebView(而非UI)来完成此任务。我很幸运地遇到this site,为我提供了以下答案,非常适合我的需求。这可能会帮助路人寻找与我相同的答案。

使用此功能(来自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)
}

答案 8 :(得分:-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”);

}