What is NSCache, and how is it different from a Dictionary?

2.7.1 · L2 · Interview

Predict first

Does this compile?

let cache = NSCache<String, Data>()
  • Yes
  • No

Predict first

Does this compile?

final class Box<T> { let value: T; init(_ v: T) { value = v } }
let cache = NSCache<NSString, Box<Int>>()
  • Yes
  • No

Mental model. NSCache is a desk the cleaner may clear whenever the office gets crowded. Keep only things you can fetch again.

NSCache is an in-memory key-value store built for disposable data. It is thread-safe, it does not copy its keys, and the system may evict items at any time, especially under memory pressure or when the app goes to the background. You must always handle a miss. A Dictionary never forgets and is not thread-safe.

The limits are hints: countLimit and totalCostLimit tell it when it may start evicting, but there is no guarantee about when or in which order (it is not documented as LRU). Because it is an Objective-C class, both key and value must be class types: NSCache<NSString, UIImage>, or wrap a struct in a small final class. Nothing is persisted: it is empty on the next launch.

NSCache requires class types for both parameters, and String and Data are structs. Use NSString and NSData, or wrap the value in a class.

A small class wrapper gives you a reference type, which is what NSCache asks for.

Common traps

  • Assuming an object you just added is still there. Always code the miss path.
  • Relying on countLimit as exact. It is a hint, not a contract.

They might follow up with

  • What does the cost value do? You supply a size for each item (for images, the byte count) and totalCostLimit caps the sum.
  • Can I observe evictions? Yes, via the delegate’s willEvictObject, but do not depend on timing.

Related questions

  • 2.7.2 How would you design an in-memory image cache?
  • 2.7.5 Is Array thread-safe, and how do you make shared state safe?

How would you design an in-memory image cache? →