How to use custom type as a key for NSCache
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.