Item 50: Use NSCache Instead of NSDictionary for Caches
A common problem encountered when developing a Mac OS X or an iOS application that downloads images from the Internet is deciding what to do about caching them. A good first approach is to use a dictionary to store in memory images that have been downloaded, such that they don’t need to be downloaded again if they are requested later. A naïve developer will simply use an NSDictionary
(or rather a mutable one) because that’s a commonly used class. However, an even better class, called NSCache
, is also part of the Foundation framework and has been designed exactly for this task.
The benefit of NSCache
over an NSDictionary
is that as system memory becomes full, the cache is automatically pruned. When using a dictionary, you often end up having to write pruning code yourself by hooking into system notifications for low memory. However, NSCache
offers this automatically; because it is part of the Foundation framework, it will be able to hook in deeper to the system than you could yourself. An NSCache
will also prune the least recently used objects first. Writing the code to support this yourself with a dictionary would be quite complex.
Also, an NSCache
does not copy keys but rather retains them. This is something that can be controlled on NSDictionary
but requires more complex code (see Item 49). A cache usually would rather not copy the keys because often, the key will be an object that does not support copying. Since NSCache
doesn’t copy by default, it makes it an easier class to work with in these situations. Also, NSCache
is thread safe. This is certainly not true of an NSDictionary
, which means that you can poke away at an NSCache
from multiple threads at the same time without having to introduce any locks of your own. This is usually useful for a cache because you may want to read from it in one thread, and, if a certain key doesn’t exist, you may download the data for that key. The callbacks for downloading may be in a background thread, so you end up adding to the cache in this other thread.