iOS 7 UIWebView 304 cache bug, blank pages

瘦欲@ 提交于 2019-12-04 07:10:30
LordT

As the other questions are to use the NSURLConnection every time, which seems like a bit of an overhead: Why don't you execute a small javascript after the page was loaded (complete or incomplete) that can tell you if the page is actually showing? Query for a tag that should be there (say your content div) and give a true/false back using the

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

And then, should that return false, you can reload the URL manually using the cache-breaker technique you described yourself:

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

[edit]

based on the discussion in the comments and some of the other answers, I think you might have the best solution manually changing the NSURLCache.

From what I gathered, you're mainly trying to solve a reload/reshow scenario. In that case, query the NSURLCache if a correct response is there, and if not delete the storedvalue before reloading the UIWebView.

[edit 2]

based on your new results, try to delete the NSURLCache when it is corrupted:

- (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;
}

We might have to refine the check if the cache is invalid again, but in theory this should do the trick!

You can implement a NSURLProtocol, and then in +canonicalRequestForRequest: modify the request to override the cache policy.

This will work for all requests made, including for static resources in the web view which are not normally consulted with the public API delegate.

This is very powerful, and yet, rather easy to implement.

Here is more information: http://nshipster.com/nsurlprotocol/

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


Here is an example:

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

When creating NSURLRequest instance, you can set Cache Policy. Hope it works!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!