我想在收到HTTP错误404等时通知用户。我怎么能检测出来? 我已经尝试过实施
了- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
但是当我收到404错误时它没有被调用。
答案 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状态代码等向用户显示相应的错误消息。
答案 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”);
}