ios 如何检测和处理 UIWebView 中的 HTTP 错误代码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2236407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to detect and handle HTTP error codes in UIWebView?
提问by EEE
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 错误时它不会被调用。
采纳答案by Felix Lamouroux
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.
不是很优雅,但它可能会起作用。
回答by Axel Guilmin
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,并且响应被认为是无错误的。
回答by Matt Long
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 视图不会解释内容中的错误。来自 UIWebViewDelegate Apple Docs 的 -didFailLoadWithError 的目的是:
Sent if a web view failed to load content.
在 Web 视图加载内容失败时发送。
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,
此致,
回答by William Denniss
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应该永远是一个NSHTTPURLResponse HTTP请求......但你可能是明智的,以防万一有一个断言那里。
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!
注意。我真的不建议您为错误消息解析 NSData 对象。这就是 HTTP 'statusCode' 的用途!
回答by Ahmet Ardal
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.
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 *)responsemethod 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.
并且您在收到响应后不需要继续加载请求。你可以在- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response方法中取消连接,在了解 HTTP 状态码后。这样可以防止连接加载任何不必要的响应数据。然后您可以再次在 UIWebView 中加载请求或根据 HTTP 状态代码等向用户显示适当的错误消息。
回答by AlienFromCA
I am new to iOS and Swift development, and needed to find a way to accomplish this as well, using WKWebView (not UI). I was fortunate enough to run across this sitethat gave me the following answer, which works perfectly for my needs. It might help passers-by that are looking for the same answer I was.
我是 iOS 和 Swift 开发的新手,需要找到一种方法来实现这一点,使用 WKWebView(而不是 UI)。我有幸浏览了这个网站,它给了我以下答案,非常适合我的需求。它可能会帮助那些正在寻找与我相同答案的路人。
Using this function (from WKNavigationDelegate):
使用这个函数(来自 WKNavigationDelegate):
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)
You can create custom responses based on the HTTP response, like so:
您可以根据 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)
}
回答by Radu Simionescu
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 通常会被具有默认配置的系统缓存。
回答by Mindhavok
Heres is my swift 3 version of @AxelGuilmin response:
这是我对@AxelGuilmin 回复的 swift 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
}
}
}
回答by Hardik Mamtora
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”);
}
}