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

EEE*_*EEE 19 iphone objective-c uiwebview nserror ios

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

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
Run Code Online (Sandbox Code Playgroud)

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

Axe*_*min 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
    }
}
Run Code Online (Sandbox Code Playgroud)

它管理HTTP客户端错误(4xx)和HTTP服务器错误(5xx).

请注意,如果未缓存响应,则cachedResponseForRequest返回nil,在这种情况下,将返回statusCode为0,并且响应被视为无错误.

  • 但是很多时候`cachedResponseForRequest`返回`Nil` (2认同)

Fel*_*oux 9

你可以在这里捕获URLRequest:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
Run Code Online (Sandbox Code Playgroud)

并将请求交给代表并返回否.然后在收到的响应调用中NSURLConnection取消连接,如果一切正常(检查响应),再次在webview中加载urlrequest.再次加载urlrequest时,请确保在上面的调用中返回YES.

不是很优雅,但它可能会奏效.

  • 这意味着每次请求两次......这是错误的 (5认同)

Ahm*_*dal 8

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

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

这是文章

这是github上的演示项目


Mat*_*ong 7

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

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

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

404或Not Found错误消息是HTTP标准响应代码,表示客户端能够与服务器通信但服务器无法找到所请求的内容.404错误不应与"未找到服务器"或类似错误相混淆,其中根本无法与目标服务器建立连接.

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

最好的祝福,


Wil*_*iss 7

NSURLConnection是您正在寻找的类,我不认为这可以直接在UIWebView中完成.

您可以使用同步方法

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
Run Code Online (Sandbox Code Playgroud)

或者是异步的.这些更难设置,因为你必须将你获得的所有数据都附加到1 NSData中,但最终结果是相同的.


无论您使用同步还是异步方法:

如果你得到一个NSError*对象,那么就会出现COMMS错误.如其他响应中所述,这不是HTTP状态代码,而是通信问题.

如果连接成功,则会获得NSURLResponse和NSData.重要的是,HTTP请求的NSURLResponse实际上是NSHTTPURLResponse子类!

然后,您必须检查响应以查看错误代码是什么.试试这个(_responseInfo你的NSURLResponse对象在哪里):

  NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;
Run Code Online (Sandbox Code Playgroud)

responseInfo应该始终是HTTP请求的NSHTTPURLResponse ...但是你可能明智地在那里有一个断言以防万一.

如果statusCode成功(即200),则NSData对象应该包含响应的数据(无论可能是什么).如果状态代码指示错误,则NSData可能包含来自服务器的错误的文本描述.

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


Ali*_*mCA 5

我是 iOS 和 Swift 开发的新手,也需要找到一种方法来完成此任务,使用 WKWebView (而不是 UI)。我有幸遇到过这个网站,它给了我以下答案,它非常适合我的需求。它可能会帮助正在寻找与我相同答案的路人。

使用此函数(来自 WKNavigationDelegate):

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)
Run Code Online (Sandbox Code Playgroud)

您可以根据 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)
}
Run Code Online (Sandbox Code Playgroud)