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.
The NSURLCache class implements the caching of responses to URL load requests, by mapping NSURLRequest objects to NSCachedURLResponse objects. It provides a composite in-memory and on-disk cache, and lets you manipulate the sizes of both the in-memory and on-disk portions.
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 subclassNSURLCache
to change the behaviour of the fetch and store operations to use the disk (likeSDURLCache
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 callstoreCachedResponse:forRequest:
for files over about 50KB (>= 52428 bytes, to be exact). This makes subclassingNSURLCache
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 aboveNSURLConnection
.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/aftercurrentMemoryUsage
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
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"];
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With