简体   繁体   中英

UIWebView doesn't always call -[NSURLCache storeCachedResponse:forRequest:]

It seems that UIWebView doesn't always call storeCachedResponse:forRequest: whenever it's loading a resource. Does anyone know why? I am trying to cache images by using -[NSURLCache storeCachedResponse:forRequest:] , it does most of the job fine, however in some cases UIWebView doesn't call this method on page load where there are actually images on it.

Answering the bounty provider's query:

I'm seeing this for small files (100s of bytes) as well. The webview also fails to call cachedResponseForRequest:

I found this question that addresses this behavior directly:

Despite Apple's documentation indicating otherwise , NSURLCache on iOS doesn't do any disk (flash) caching at all. You can subclass NSURLCache to change the behaviour of the fetch and store operations to use the disk (like SDURLCache does), but due to the following severe limitations of how the cache is used and implemented, this doesn't work as well as you'd expect:

  • NSURLConnection doesn't even call storeCachedResponse:forRequest: for files over about 50KB (>= 52428 bytes, to be exact). This makes subclassing NSURLCache pointless for our use (200KB images), because it won't even get to the cache. As a result, we have to add caching manually at a level above NSURLConnection .

  • Even when one calls the NSURLCache's built-in storeCachedResponse:forRequest: manually, it only stores the response in memory if it's less than about 180KB. I tested this by calling storeCachedResponse manually and seeing that the before/after currentMemoryUsage didn't change for data lengths above about 180KB. So we have to write our own LRU memory caching too.

(Emphasis mine.)

This seems to be responsible for the behavior being called out. As the current accepted answer points out , ASIHTTPRequest is the expected workaround for this behavior.

However, note the caveat at the top of the page:

Please note that I am no longer working on this library - you may want to consider using something else for new projects. :)

You should consider relying on supported libraries or, if you prefer, contributing back to this library once it underlies your code.

As described here NSURLConnection doesn't call storeCachedResponse:forRequest: if file size over 50kb(52428 bytes).
Try ASIHTTPRequest caching .

NSURLCache works with two different caches: on-disk cache and in-memory cache

  • Responses will be cached to in-memory cache if the response size is under 50kb and
  • Responses will be cached to on-disk cache if the response size is over 50kb

If you initialize NSURLCache with diskPath nil then the on-disk cache will not be active and storeCachedResponse:forRequest: will only be called for response sizes that are under 50kb.

So configure your URLCache like this

[[MYCustomURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 
                          diskCapacity:20 * 1024 * 1024 
                          diskPath:@"urlcache.db"];

我不确定UIWebvieuw是如何工作的,但是当你使用NSURLRequest时,文件的最大大小取决于你如何初始化URLCache(initWithMemoryCapacity:(NSUInteger)memoryCapacity ...)我刚刚缓存了一个2MB的文件

Have you checked HTTP status and cache headers? Expires, Cache-Control etc? Maybe a server answers with status=304 without any response body?

- (void)connection:(NSURLConnection *)conn didReceiveResponse:(NSURLResponse *)aResponse 
{
  NSLog(@"CODE: %d", ((NSHTTPURLResponse *)aResponse).statusCode);
  NSLog(@"HEADERS: %@", ((NSHTTPURLResponse *)aResponse).allHeaderFields);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM