iOS 7 UIWebView 304caching错误,空白页面

我有一个问题,我发现在我的应用程序有一个UIWebView。 iOS 7caching空白主体304响应,导致用户刷新UIWebView时显示空白页面。 这是不好的用户expierience,我想弄清楚如何解决这个在iOS端,因为我没有控制如何亚马逊S3响应头(这是我用于我的资源托pipe)。

这些bug的更多细节被这些人发现: http : //tech.vg.no/2013/10/02/ios7-bug-shows-white-page-when-getting-304-not-modified-from-server /

我会很感激提供的任何帮助,如何我可以在应用程序端而不是服务器端解决这个问题。

谢谢。

更新:使用赏金的build议修正这个错误作为指导:

@property (nonatomic, strong) NSString *lastURL; - (void)webViewDidFinishLoad:(UIWebView *)webView { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; if ([self.webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"].length < 1) { NSLog(@"Reconstructing request..."); NSString *uniqueURL = [NSString stringWithFormat:@"%@?t=%@", self.lastURL, [[NSProcessInfo processInfo] globallyUniqueString]]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:uniqueURL] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0]]; } } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { self.lastURL = [request.URL absoluteString]; return YES; } 

由于其他问题是每次使用NSURLConnection,这似乎是一个开销:为什么你不执行一个小的JavaScript后页面加载(完整或不完整),可以告诉你,如果页面实际上显示? 查询应该在那里的标签(说你的内容股利),并使用

 [UIWebView stringByEvaluatingJavaScriptFromString:@"document.getElementById('adcHeader')!=null"] 

然后,如果返回false,则可以使用您自己描述的caching断路器技术手动重新加载URL:

 NSString *uniqueURL = [NSString stringWithFormat:@"%@?t=%d", self.url, [[NSDate date] timeIntervalSince1970]]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:uniqueURL] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:5.0]]; 

[编辑]

基于评论和其他一些答案的讨论,我想你可能有最好的解决scheme,手动更改NSURLCache

从我收集的信息来看,你主要是试图解决一个重载/重做的情况。 在这种情况下,查询NSURLCache是否存在正确的响应,如果在重新加载UIWebView之前没有删除存储值。

编辑2

根据您的新结果,尝试删除损坏的NSURLCache

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache]cachedResponseForRequest:request]; if (cachedResponse != nil && [[cachedResponse data] length] > 0) { NSLog(@"%@",cachedResponse.response); } else { [[NSURLCache sharedURLCache] removeCachedResponseForRequest:request]; } return YES; } 

如果caching无效,我们可能不得不完善检查,但从理论上讲,这应该是个诀窍!

你可以实现一个NSURLProtocol ,然后在+canonicalRequestForRequest:修改请求来覆盖caching策略。

这将适用于所有请求,包括Web视图中的静态资源,这些资源通常不会与公共API委托进行协商。

这是非常强大的,但是实现起来相当容易。

以下是更多信息: http : //nshipster.com/nsurlprotocol/

参考: https : //developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Classes/NSURLProtocol_Class/Reference/Reference.html


这里是一个例子:

 @interface NoCacheProtocol : NSURLProtocol @end @implementation NoCacheProtocol + (void)load { [NSURLProtocol registerClass:[NoCacheProtocol class]]; } + (BOOL)canInitWithRequest:(NSURLRequest*)theRequest { if ([NSURLProtocol propertyForKey:@“ProtocolRequest” inRequest:theRequest] == nil) { return YES; } return NO; } + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)theRequest { NSMutableURLRequest* request = [theRequest mutableCopy]; [request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData]; //Prevent infinite recursion: [NSURLProtocol setProperty:@YES forKey:@"ProtocolRequest" inRequest:request]; return request; } - (void)startLoading { //This is an example and very simple load.. [NSURLConnection sendAsynchronousRequest:self.request queue:[NSOperationQueue currentQueue] completionHandler:^ (NSURLResponse* response, NSData* data, NSError* error) { [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; [[self client] URLProtocol:self didLoadData:data]; [[self client] URLProtocolDidFinishLoading:self]; }]; } - (void)stopLoading { NSLog(@"something went wrong!"); } @end 
 NSURL *URL = [NSURL URLWithString:@"http://mywebsite.com"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0]; [myWebView loadRequest: request]; 

创buildNSURLRequest实例时,可以设置caching策略。 希望它的作品!