3
votes

The option to not cache data is NSDataReadingUncached.

But if I use dataWithContentsOfURL to update the images from URLs in a UITableViewCell (one image per cell), and I look at the Activities Monitor on the Mac for the Simulator (running as iOS 5.1 simulator), then the network traffic jumps up to 12kb/s receiving rate when I scroll the table up and down continuously. When I stopped scrolling up and down, the network activities drops down to about 2kb/s receiving rate or lower. Those images are very small, like 20kb or so each, and when I scroll up and down, I only make 1 or 2 image disappear / appear, so the cache, if any, won't need to be large at all.

So it does look like dataWithContentsOfURL does not cache data, and even when I use dataWithContentsOfURL:options:error: with options being 0 to mean no option, the network activities still jump up to about 12kb/s.

So does dataWithContentsOfURL caches data, and if not, why does dataWithContentsOfURL:options:error: has the option of not cache data?

The following is also done:

[[NSURLCache sharedURLCache] setMemoryCapacity:1024*1024*10];

in viewDidLoad but the network rate still will jump up. I think the usual recommendation is that if caching is desired, then use NSURLConnection, but for some reason, in the NSURLConnection reference on Apple's doc, the word "cache" or "caching" doesn't appear at all except there is mentioning of a sample project called "URLCache", but no mentioning of caching at all.

1

1 Answers

9
votes

We're talking about two different caches here, the file-system cache, and the network cache.

The flag you can pass into dataWithContentsOfURL:options:error: (NSDataReadingUncached) refers to the former. It's a hint that the data you're reading will only be read once, so it doesn't need to linger in the cache. You might be surprised to learn that the file-system cache is involved at all here, since we're reading from a URL, but remember that the URL might be a file URL, in which case the read occurs from disk rather than generating a network request.

As to the other type of cache, the network cache, you don't have any say whether loading the contents of a URL using the NSData convenience methods uses caching or not: it doesn't. For that behavior, you have to use a lower-level API like NSURLConnection, as you mentioned. Note that in order to take advantage of HTTP caching at this level, your server needs to send the proper headers indicating how long resources are valid. Otherwise, the request will be made under the pessimistic assumption that the resource has changed. NSURLConnection on iOS will automatically use NSURLCache under the sheets, again provided that Expires/Cache-Control headers are received.

Sidenote: When using NSURLConnection, you set the cache policy not on the connection, but on the NSURLRequest object(s) you use to make requests with the connection. So, you'd need to look at the reference for NSURLRequest and its ilk to find out the details.

If none of the above is suitable to you, you can roll your own cache scheme, or start with NSURLCache and use it directly. As of iOS 5, NSURLCache started using disk caching and honoring the diskCapacity property, making it even more powerful than before. This is the right way to go if you have some sort of out-of-band knowledge of how long the resources will stay fresh, above and beyond what your HTTP server is telling you.