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

时间:2021-08-07 03:06:28

I want to inform user when HTTP error 404 etc is received. How can I detect that? I've already tried to implement

当收到HTTP错误404等时,我想通知用户。我怎么能发现呢?我已经试过实现了

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

but it is not called when I receive 404 error.

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

8 个解决方案

#1


7  

You could capture the URLRequest here:

您可以在这里捕获URLRequest:

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

and hand the request over to the delegate and return no. Then in the received response call from NSURLConnection cancel the connection and if everything is fine (check response) load the urlrequest once more in the webview. Make sure to return YES in the above call when loading the urlrequest again.

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

Not very elegant, but it might work.

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

#2


18  

My implementation inspired by Radu Simionescu's response :

受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
    }
}

It manages HTTP client errors (4xx) and HTTP server errors (5xx).

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

Note that cachedResponseForRequest returns nil if the response is not cached, in that case statusCode is assigned to 0 and the response is considered errorless.

注意,如果没有缓存响应,cachedResponseForRequest将返回nil,在这种情况下,statusCode被分配为0,而响应被认为是无错误的。

#3


8  

UIWebView does not provide any functionality for getting HTTP status codes for the requests it loads. One workaround is to intercept the request loading process of UIWebView using the UIWebViewDelegate methods and use NSURLConnection to detect how the server responds to that request (as suggested above). Then you can take an appropriate action suitable for the situation. This article explains the workaround in detail on a demo project.

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

And you don't need to continue loading the request after you received a response. You can just cancel the connection in - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response method after learning the HTTP status code. This way you prevent the connection from loading any unnecessary response data. Then you can load the request in UIWebView again or show an appropriate error message to the user depending on the HTTP status code, etc.

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

Here is the article

这是这篇文章

and here is the demo project on github

这是github上的演示项目

#4


7  

You're mis-interpreting what -didFailLoadWithError is for. Technically, the request succeeded. It was able to hit the server and find that the file you're requesting doesn't exist (i.e. 404). The -didFailLoadWithError method will get called if the server doesn't exist, for example. Your server exists. The file doesn't. The web view is not going to interpret errors in the content. The purpose of -didFailLoadWithError from the UIWebViewDelegate Apple Docs is:

你误解了didfailloadwitherror是什么。从技术上讲,请求成功了。它能够攻击服务器并发现您请求的文件不存在(即404)。例如,如果服务器不存在,则会调用-didFailLoadWithError方法。您的服务器的存在。该文件不存在。web view不会解释内容中的错误。来自UIWebViewDelegate Apple Docs的-didFailLoadWithError的目的是:

Sent if a web view failed to load content.

如果web view未能加载内容,则发送。

From the Wikipedia article on HTTP 404:

从*上关于HTTP 404的文章:

The 404 or Not Found error message is a HTTP standard response code indicating that the client was able to communicate with the server but the server could not find what was requested. 404 errors should not be confused with "server not found" or similar errors, in which a connection to the destination server could not be made at all.

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

In all likelihood you'll have to parse the response text for a 404 which you could obtain with an NSURLConnection/NSURLRequest combination rather than a web view.

您可能需要解析404的响应文本,您可以通过NSURLConnection/NSURLRequest组合而不是web视图获得该文本。

Best Regards,

最好的问候,

#5


7  

NSURLConnection is the class you are looking for, I don't think this can be done directly in a UIWebView.

NSURLConnection是您要查找的类,我不认为它可以直接在UIWebView中完成。

You can use the synchronous method

您可以使用同步方法

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

Or the Asynchronous ones. These are harder to setup as you have to append all the bits of data you get into the 1 NSData, but the end result is the same.

或者是异步的。这些设置比较困难,因为您必须将获得的所有数据添加到1个NSData中,但是最终结果是相同的。


Regardless of if you use the Synchronous or Asynchronous methods:

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

If you get a NSError* object then there was a COMMS error. As noted in the other responses, this is NOT a HTTP status code but rather a communication problem.

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

If the connection succeeded, you get an NSURLResponse and NSData. Importantly the NSURLResponse for HTTP requests is actually the NSHTTPURLResponse subclass!

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

Then you must check the response to see what the error code is. Try this (where _responseInfo is your NSURLResponse object):

然后您必须检查响应以查看错误代码是什么。试试这个(_responseInfo是NSURLResponse对象):

  NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;

responseInfo should always be a NSHTTPURLResponse for HTTP requests... but you might be wise to have an assert there just in case.

responseInfo应该始终是针对HTTP请求的NSHTTPURLResponse…但是你最好在那里有一个断言以防万一。

IF the statusCode is a success (i.e. 200) then your NSData object should contain the data of the response (whatever that may be). If the status code indicates an error then the NSData may contain a textual description of the error from the server.

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

NB. I really don't recommend tyring to parse the NSData object for the error message. That's what the HTTP 'statusCode' is for!

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

#6


2  

In webViewDidFinishLoad:

在webViewDidFinishLoad:

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

You may consider this solution over other more complex ones, even though some responses might not get cached. Note that wrong urls are usually getting cached by a system which has default configurations.

与其他更复杂的解决方案相比,您可以考虑此解决方案,尽管有些响应可能不会被缓存。注意,错误的url通常被具有默认配置的系统缓存。

#7


1  

Heres is my swift 3 version of @AxelGuilmin response:

以下是我的swift 3版本的@AxelGuilmin回复:

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
            }
        }
    }

#8


-1  

I used below code for my solution

我使用了下面的代码作为我的解决方案

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

}

}

#1


7  

You could capture the URLRequest here:

您可以在这里捕获URLRequest:

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

and hand the request over to the delegate and return no. Then in the received response call from NSURLConnection cancel the connection and if everything is fine (check response) load the urlrequest once more in the webview. Make sure to return YES in the above call when loading the urlrequest again.

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

Not very elegant, but it might work.

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

#2


18  

My implementation inspired by Radu Simionescu's response :

受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
    }
}

It manages HTTP client errors (4xx) and HTTP server errors (5xx).

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

Note that cachedResponseForRequest returns nil if the response is not cached, in that case statusCode is assigned to 0 and the response is considered errorless.

注意,如果没有缓存响应,cachedResponseForRequest将返回nil,在这种情况下,statusCode被分配为0,而响应被认为是无错误的。

#3


8  

UIWebView does not provide any functionality for getting HTTP status codes for the requests it loads. One workaround is to intercept the request loading process of UIWebView using the UIWebViewDelegate methods and use NSURLConnection to detect how the server responds to that request (as suggested above). Then you can take an appropriate action suitable for the situation. This article explains the workaround in detail on a demo project.

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

And you don't need to continue loading the request after you received a response. You can just cancel the connection in - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response method after learning the HTTP status code. This way you prevent the connection from loading any unnecessary response data. Then you can load the request in UIWebView again or show an appropriate error message to the user depending on the HTTP status code, etc.

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

Here is the article

这是这篇文章

and here is the demo project on github

这是github上的演示项目

#4


7  

You're mis-interpreting what -didFailLoadWithError is for. Technically, the request succeeded. It was able to hit the server and find that the file you're requesting doesn't exist (i.e. 404). The -didFailLoadWithError method will get called if the server doesn't exist, for example. Your server exists. The file doesn't. The web view is not going to interpret errors in the content. The purpose of -didFailLoadWithError from the UIWebViewDelegate Apple Docs is:

你误解了didfailloadwitherror是什么。从技术上讲,请求成功了。它能够攻击服务器并发现您请求的文件不存在(即404)。例如,如果服务器不存在,则会调用-didFailLoadWithError方法。您的服务器的存在。该文件不存在。web view不会解释内容中的错误。来自UIWebViewDelegate Apple Docs的-didFailLoadWithError的目的是:

Sent if a web view failed to load content.

如果web view未能加载内容,则发送。

From the Wikipedia article on HTTP 404:

从*上关于HTTP 404的文章:

The 404 or Not Found error message is a HTTP standard response code indicating that the client was able to communicate with the server but the server could not find what was requested. 404 errors should not be confused with "server not found" or similar errors, in which a connection to the destination server could not be made at all.

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

In all likelihood you'll have to parse the response text for a 404 which you could obtain with an NSURLConnection/NSURLRequest combination rather than a web view.

您可能需要解析404的响应文本,您可以通过NSURLConnection/NSURLRequest组合而不是web视图获得该文本。

Best Regards,

最好的问候,

#5


7  

NSURLConnection is the class you are looking for, I don't think this can be done directly in a UIWebView.

NSURLConnection是您要查找的类,我不认为它可以直接在UIWebView中完成。

You can use the synchronous method

您可以使用同步方法

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

Or the Asynchronous ones. These are harder to setup as you have to append all the bits of data you get into the 1 NSData, but the end result is the same.

或者是异步的。这些设置比较困难,因为您必须将获得的所有数据添加到1个NSData中,但是最终结果是相同的。


Regardless of if you use the Synchronous or Asynchronous methods:

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

If you get a NSError* object then there was a COMMS error. As noted in the other responses, this is NOT a HTTP status code but rather a communication problem.

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

If the connection succeeded, you get an NSURLResponse and NSData. Importantly the NSURLResponse for HTTP requests is actually the NSHTTPURLResponse subclass!

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

Then you must check the response to see what the error code is. Try this (where _responseInfo is your NSURLResponse object):

然后您必须检查响应以查看错误代码是什么。试试这个(_responseInfo是NSURLResponse对象):

  NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;

responseInfo should always be a NSHTTPURLResponse for HTTP requests... but you might be wise to have an assert there just in case.

responseInfo应该始终是针对HTTP请求的NSHTTPURLResponse…但是你最好在那里有一个断言以防万一。

IF the statusCode is a success (i.e. 200) then your NSData object should contain the data of the response (whatever that may be). If the status code indicates an error then the NSData may contain a textual description of the error from the server.

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

NB. I really don't recommend tyring to parse the NSData object for the error message. That's what the HTTP 'statusCode' is for!

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

#6


2  

In webViewDidFinishLoad:

在webViewDidFinishLoad:

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

You may consider this solution over other more complex ones, even though some responses might not get cached. Note that wrong urls are usually getting cached by a system which has default configurations.

与其他更复杂的解决方案相比,您可以考虑此解决方案,尽管有些响应可能不会被缓存。注意,错误的url通常被具有默认配置的系统缓存。

#7


1  

Heres is my swift 3 version of @AxelGuilmin response:

以下是我的swift 3版本的@AxelGuilmin回复:

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
            }
        }
    }

#8


-1  

I used below code for my solution

我使用了下面的代码作为我的解决方案

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

}

}