Swift で NSCache を Generics にして便利に
上記の記事を参考にキャッシュのジェネリクスを書いたところ、
Swift5.0.1だと動かなかったのと、
NSCacheとインターフェイスが違うのが個人的には好きじゃなかったので、下記のように書き換えてみました。
GenericCache
//KeyTypeがT, ObjectTypeがU
class GenericCache<T, U> {
private var cache = NSCache<AnyObject, AnyObject>()
var delegate: NSCacheDelegate? {
get { return self.cache.delegate }
set { self.cache.delegate = newValue }
}
var name: String {
get { return self.cache.name }
set { self.cache.name = newValue }
}
func object(forKey: T) -> U? {
let forKey = forKey as AnyObject
return self.cache.object(forKey: forKey) as? U
}
func setObject(_ obj: U, forKey key: T) {
let obj = obj as AnyObject
let key = key as AnyObject
self.cache.setObject(obj, forKey: key)
}
func setObject(_ obj: U, forKey key: T, cost g: Int) {
let obj = obj as AnyObject
let key = key as AnyObject
self.cache.setObject(obj, forKey: key, cost: g)
}
func removeObject(forKey: AnyObject) {
self.cache.removeObject(forKey: forKey)
}
func removeAllObjects() {
self.cache.removeAllObjects()
}
var totalCostLimit: Int {
get { return self.cache.totalCostLimit }
set { self.cache.totalCostLimit = newValue }
}
var countLimit: Int {
get { return self.cache.countLimit }
set { self.cache.countLimit = newValue }
}
var evictsObjectsWithDiscardedContent: Bool {
get { return self.cache.evictsObjectsWithDiscardedContent }
set { self.cache.evictsObjectsWithDiscardedContent = newValue }
}
}
呼び出し例
//インスタンス化
let cache = GenericCache<String, UIImage>()
cache.countLimit = 1000
//キャッシュする処理
let key = "cat"
let image = UIImage(url: url) //そういうurlがあるとして
cache.setObject(image, forKey: key)
//取り出し
let catImage = cache.object(forKey: key) //UIImage?が返る
本で読んで知識としては知っていたもののなかなか実装に使えなかった、
ジェネリクスをはじめて使えたので嬉しかったです。
あと
「All paths through this function will call itself」というワーニングが、
delegateのGetterとevictsObjectsWithDiscardedContentのSetterで出ます。
かといってGetterとSetterを定義しないと怒られるので、仕方ないですね。
⇒2019/08/23追記
人から指摘されて気づきましたが、self「.cache」が抜けていました。。。
今は修正しています