我想检测到给UIWebView的页面加载请求何时返回了5xx或4xx范围内的状态代码。
我已经为Web视图设置了委托,并提供了一个-webView:didFailLoadWithError:错误方法,但是虽然它被称为超时超时,但是没有调用HTTP状态代码错误。
有什么建议吗?
答案 0 :(得分:10)
嗯......我不是iPhone开发者,但是......
您是否可以尝试使用要加载的网址创建NSURLRequest?然后你可以使用NSURLConnection进行连接。
NSURLConnection有一个委托方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
将从服务器给出响应。请注意,如果您通过HTTP建立连接,则响应实际上是NSHTTPURLResponse类。 NSHTTPURLResponse可用于使用以下实例方法获取状态
- (NSInteger)statusCode
NSURLConnection有另一个委托方法
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
可用于从URL连接获取数据。然后,您可以使用以下方法手动将数据加载到UIWebView中:
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
这似乎很多工作,但可以做到。希望其他人能提出更简单的方法,虽然我没有看到它。
答案 1 :(得分:4)
我努力寻找一个好的答案已经挣扎了很长一段时间。我正在工作的要求是我需要能够确定FIRST页面加载的状态,以及之后的任何加载我会假设用户点击了不应该被破坏的链接(不保证,我知道,但比替代品好很多)。
我最终做的是通过NSURLConnection(同步)自己进行初始调用,然后将数据传递给UIWebView。
NSURL *googleURL = [NSURL URLWithString:@"http://www.google.com"];
NSURLRequest *googleRequest = [NSURLRequest requestWithURL:googleURL];
NSHTTPURLResponse *response;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:googleRequest
returningResponse:&response
error:&error];
if ([response statusCode] >= 400 || error)
{
// handle error condition
} else {
[webView_ loadData:responseData MIMEType:[response MIMEType]
textEncodingName:[response textEncodingName]
baseURL:[response URL]];
[self setView:webView_];
}
如果您希望获取每个请求的信息,只需使用方法
即可- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
拦截所有请求并自行制作。您必须拥有某种请求管理技术,因为当您在UIWebView上调用loadData时,它将调用shouldStartLoadWithRequest回调,并且您希望确保不执行无限循环以发出相同的请求。结束了。
答案 2 :(得分:3)
现在,当事情发生在 Swift 3.0 时,我在这个话题上非常努力。我甚至创建了一个自定义URLProtocol,并尝试拦截所有Web请求,只是为了最终意识到它是不必要的。我感到困惑的原因是因为他们移动了didReceiveResponse函数:
optional public func connection(_ connection: NSURLConnection, didReceive response: URLResponse)
到 NSURLConnectionDataDelegate ,它继承自NSURLConnectionDelegate。
无论如何,这是适用的Swift 3.0版本:
// You first need to have NSURLConnectionDataDelegate on your UIWebView
// MARK: - get HTTP status code
// setup urlconnectiondelegate
// so that the didReceiveResponse is called
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let conn: NSURLConnection? = NSURLConnection(request: request, delegate: self)
if conn == nil {
print("cannot create connection")
}
return true;
}
// intercept the actual http status code
func connection(_ connection: NSURLConnection, didReceive response: URLResponse) {
let httpResponse: HTTPURLResponse = response as! HTTPURLResponse;
print(httpResponse.statusCode)
}
答案 3 :(得分:2)
目前,UIWebView不提供任何获取其加载的请求的HTTP状态代码的功能。一种解决方法是使用UIWebViewDelegate方法拦截UIWebView的请求加载过程,并使用NSURLConnection检测服务器如何响应该请求。然后你可以采取适合这种情况的适当行动。 This article详细解释了演示项目的解决方法。
收到回复后,您无需继续加载请求。在学习HTTP状态代码后,您可以在 - (void)连接:(NSURLConnection *)连接didReceiveResponse:(NSURLResponse *)响应方法中取消连接。这样可以防止连接加载任何不必要的响应数据。然后,您可以再次在UIWebView中加载请求,或者根据HTTP状态代码等向用户显示相应的错误消息。
答案 4 :(得分:2)
以下是获取HTTP响应代码的解决方法,但只向每个网址发送一个请求: -
BOOL isLoad;
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSLog(@"Requesting: %@ - %d - %@", request.URL.absoluteString, navigationType, request.URL.host);
if (navigationType != UIWebViewNavigationTypeOther) {
//Store last selected URL
self.loadedURL = request.URL.absoluteString;
}
if (!isLoad && [request.URL.absoluteString isEqualToString:loadedURL]) {
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError || ([response respondsToSelector:@selector(statusCode)] && [((NSHTTPURLResponse *)response) statusCode] != 200 && [((NSHTTPURLResponse *)response) statusCode] != 302)) {
//Show error message
[self showErrorMessage];
}else {
isLoad = YES;
[_wbView loadData:data MIMEType:[response MIMEType]
textEncodingName:[response textEncodingName]
baseURL:[response URL]];
}
}];
return NO;
}
isLoad = NO;
return YES;
}
答案 5 :(得分:1)
正如我刚刚在another thread上发布的那样,也可以拦截NSURLRequest
级别的任何NSURLProtocol
并在那里创建NSURLResponse
,而不是在你的{{1}} UIWebView委托/控制器。在我看来,这更好的原因是它维护了UIWebView的后/前导航堆栈。这个方法的大纲可以在Rob Napier的这篇优秀博客文章中找到:
http://robnapier.net/blog/offline-uiwebview-nsurlprotocol-588
以及GitHub上的代码:
答案 6 :(得分:0)
这是一个很好的例子,他们使用组合为第一次加载创建NSURLConnection,并为下一页创建UIWebView:
http://www.ardalahmet.com/2011/08/18/how-to-detect-and-handle-http-status-codes-in-uiwebviews/
基本上这是主要技巧,使用shouldStartLoadRequest的YES / NO返回值:
- (BOOL) webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if (_sessionChecked) {
// session already checked.
return YES;
}
// will check session.
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
if (conn == nil) {
NSLog(@"cannot create connection");
}
return NO;
}
这可以让你在不使用同步请求的情况下前进,尤其是与Jeff的回答相结合。
答案 7 :(得分:-4)
可悲的是,目前看来最好的选择是使用-stringByEvaluatingJavaScriptFromString:运行某种小脚本来查询文档的状态代码。
答案 8 :(得分:-6)
如何在webViewDidFinishLoad:
上实施UIWebViewDelegate
,并使用UIWebView的request
属性访问您感兴趣的标题?像这样(未经测试):
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString* theStatus = [[webView request] valueForHTTPHeaderField:@"Status"];
}