0
votes

I need to show a UIWebView that opens a local html, fetching from a remote server. Each time, the UIWebView shows incorrect data, because the iOS caching system.

I did many attempts to solve this problem, but it does not work:

1) Programmatically add UIWebView when the UIViewController starts loading. After the UIViewController disappears, stop loading the UIWebView, and release the UIWebView.

2) Ignore the local cache data:


NSURL *websiteUrl = [NSURL fileURLWithPath:localHtmlPath];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:websiteUrl];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[self.webView loadRequest:request];

3) Clear the cache when the UIViewController disappears


[[NSURLCache sharedURLCache] removeAllCachedResponses];
    for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {

        if([[cookie domain] isEqualToString:localHtmlPath]) {

            [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
        }
    }

4) Disable the cache


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
    [NSURLCache setSharedURLCache:sharedCache];
}

5) Reduce iOS memory utilization by taming NSURLCache

follow the tutorial link


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    int cacheSizeMemory = 4*1024*1024; // 4MB
    int cacheSizeDisk = 32*1024*1024; // 32MB
    NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"];
    [NSURLCache setSharedURLCache:sharedCache];
}

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
    [[NSURLCache sharedURLCache] removeAllCachedResponses];
}

6) Follow this link to prevent CSS caching.

None of these above methods works. Any workaround?

1

1 Answers

1
votes

As far as I know, the latest SDK iOS8.0 has a bug in cache. Further, when loading local html file the NSURLCache is not used. The UIWebView has its own cache which can not be controlled by us. My solution is following.

1) Use the subclass of NSURLProtocol class which intercepts loading HTML file. The response header can be modified in order to insert no-cache headers. For example, for the scheme file://,

- (void)startLoading 
{
    NSData *data = [NSData dataWithContentsOfFile:self.request.URL.path];
    NSDictionary *headers = [NSDictionary dictionaryWithObjectsAndKeys:
                         [self.request.allHTTPHeaderFields objectForKey:@"Accept"], @"Accept",
                         @"no-cache", @"Cache-Control",
                         @"no-cache", @"Pragma",
                         [NSString stringWithFormat:@"%d", (int)[data length]], @"Content-Length",
                         nil];
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:request.URL
                                       statusCode:200
                                      HTTPVersion:@"1.1"
                                     headerFields:headers];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowedInMemoryOnly];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];

2) After loading html file which is incorrect due to the UIWebView's cache, let's reload once again. (do UIWebView.reload()) For example this can be done at webViewDidFinishLoad: method of UIWebViewDelegate. (To avoid to reload infinitely, check the reload only once by introducing flag variable) Then the reloaded html files (and other resources) are correct.

In my case, the contents become to be shown correctly by above approach.

However, we have not yet be able to clear UIWebView's cache. The memory leak of UIWebView still exists.