On iOS, since dataWithContentsOfURL:options:error: has an option to not cache data, does that mean dataWithContentsOfURL caches data?

caching, ios, nsdata, nsurlconnection

Solution

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.

Problem

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.

Original source