Error de caching UIWebView 304 de iOS 7, páginas en blanco

Tengo un problema que he descubierto en mi aplicación que tiene un UIWebView. iOS 7 almacena en caching una respuesta de cuerpo en blanco 304, lo que resulta en páginas en blanco que se muestran cuando el usuario actualiza UIWebView. Esto no es una buena experiencia de usuario y estoy tratando de descubrir cómo solucionar esto en el lado iOS, ya que no tengo control sobre cómo Amazon S3 responde a los encabezados (eso es lo que uso para mi alojamiento de resources).

Se encontraron más detalles de este error: http://tech.vg.no/2013/10/02/ios7-bug-shows-white-page-when-getting-304-not-modified-from-server /

Apreciaría cualquier ayuda ofrecida a cómo puedo resolver esto en el lado de la aplicación y no en el lado del server.

Gracias.

Actualización: corrigió este error utilizando la sugerencia de la recompensa como una guía:

@property (nonatomic, strong) NSString *lastURL; - (void)webViewDidFinishLoad:(UIWebView *)webView { [UIApplication shanetworkingApplication].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; } 

Como las otras preguntas son utilizar la NSURLConnection cada vez, lo que parece un poco de sobrecarga: ¿Por qué no se ejecuta un pequeño javascript después de que la página se cargó (completa o incompleta) que puede decirle si la página realmente se muestra ? Consulta para una label que debería estar allí (diga su div de contenido) y devuelva el valor true / false usando

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

Y luego, si esto vuelve a ser falso, puedes volver a cargar la URL manualmente usando la técnica de ruptura de caching que describiste a ti mismo:

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

[editar]

basado en la discusión en los comentarios y algunas de las otras respuestas, creo que podría tener la mejor solución para cambiar manualmente el NSURLCache .

Por lo que he recostackdo, intentas principalmente resolver un escenario de recarga / reshow. En ese caso, consulte el NSURLCache si hay una respuesta correcta y, si no, elimine el valor almacenado antes de volver a cargar el UIWebView .

[editar 2]

en function de sus nuevos resultados, intente eliminar el NSURLCache cuando esté dañado:

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

Podríamos tener que refinar el cheque si el caching no es válido nuevamente, ¡pero en teoría esto debería funcionar!

Puede implementar un NSURLProtocol y, luego, en +canonicalRequestForRequest: modificar la request para anular la política de caching.

Esto funcionará para todas las requestes realizadas, incluidos los resources estáticos en la vista web, que normalmente no se consultan con el delegado público de API.

Esto es muy poderoso y, sin embargo, bastante fácil de implementar.

Aquí hay más información: http://nshipster.com/nsurlprotocol/

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


Aquí hay un ejemplo:

 @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]; 

Al crear la instancia de NSURLRequest, puede establecer la Política de caching. ¡Espero que funcione!