How to use custom type as a key for NSCache

Oleg Dreyman
AnySuggestion
Published in
2 min readApr 18, 2017

--

NSCache is an amazing Cocoa API which is often overlooked by the developers. NSHipster has an amazing article on it, so I’ll go straight to business.

In Swift 3, NSCache is a generic type. But it doesn’t work as a regular Dictionary. In Dictionary, any Hashable type (including value types, of course) can be used as keys. But NSCache has a strange KeyType : AnyObject constraint, which means that you cannot use value types as a key (which is understandable — NSCache comes from Cocoa).

If you’re using String or IndexPath as a key, things are okay — you should just bridge those to NSString / NSIndexPath. However, using your custom type as a key can be quite tricky.

This custom type of course should be hashable, although the docs and the API itself is silent about it. But if you expect any Hashable class to work with NSCache, you’re wrong. Instead, you should subclass NSObject and override isEqual(_:) and hash. So your code should look like this:

final class CustomKey : NSObject {

let int: Int
let string: String

init(int: Int, string: String) {
self.int = int
self.string = string
}

override func isEqual(_ object: Any?) -> Bool {
guard let other = object as? CustomKey else {
return false
}
return int == other.int && string == other.string
}

override var hash: Int {
return int.hashValue ^ string.hashValue
}

}

Now you can create and use your shiny new NSCache:

let cache = NSCache<CustomKey, UIImage>()

Thanks for reading the post! Don’t hesitate to ask or suggest anything in the “responses” section below. You can also contact me on Twitter.

--

--

Oleg Dreyman
AnySuggestion

iOS development know-it-all. Talk to me about Swift, coffee, photography & motorsports.