画像をurlから取得してくる時、すでに取得済みの画像であれば再利用したいなって時があると思います
NSCacheの基本的な使い方は下のように、setObjectでキャッシュして、objectで取得するって感じです
let cache = NSCache<AnyObject, AnyObject>()
let data = "data"
let key = "key"
cache.setObject(data as AnyObject, forKey: key as AnyObject)
let cachedData = cache.object(forKey: key as AnyObject) as! String
print(cachedData) // data
だたこれだと、毎回NSChacheをinitしてるので、キャッシュしても、初期化のたびにキャッシュしたものもリセットされちゃいます
キャッシュのインスタンスは共通のものを使わないといけないです
そんな時使えるのがシングルトンです
Singleton パターンとは、そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのことである。
このシングルトンパターンを使うことで、インスタンスが1つしか生成されないことが保証されるので、
どこで使っても同じインスタンスを扱うことができます
なので実際にNSCacheのシングルトンを作ってみましょう
コードは下のようになります。
final class Cache: NSCache<AnyObject, AnyObject> {
static let sharedInstance = Cache()
private override func init() {
// 特に何もする必要なし
}
}
これだけでNSCacheのシングルトンを表現することができます
ポイントは
- finalにすること
- initをprivateにすること
1をすることで、このクラスが継承され、initとかがoverrideされて、インスタンス化されることを防ぐことができます
2をすることで、下のように初期化すると、その時点でエラーになります
なので、万が一誰かがどこかで上のようにしてインスタンス化することを防ぐことができます
let cache = Cache() // initがprivateなので外部からはアクセスできない
よって、このクラスのsharedInstanceという名前のプロパティは、どこで呼んでも同じインスタンスになっていることになります
(シングルトンの名前はsharedInstanceになることが多い)
これでどこでキャッシュしても、その値をどこでも取得することができるようになりました
NSCacheを継承してるので使い方は同じです
let url = "https://pbs.twimg.com/profile_images/991480698824409088/6j69FNqy.jpg"
if let data = Cache.sharedInstance.object(forKey: url as AnyObject) {
// すでにキャッシュされてる
self.imageView.image = UIImage(data: data as! Data)
} else {
// まだキャッシュされてない
let downloadTask = URLSession.shared.dataTask(with: URL(string: tweet.user.profileImageURL)!) { [weak self] data, _, error in
if let error = error {
print(error)
return
}
Cache.sharedInstance.setObject(data as AnyObject, forKey: url as AnyObject)
DispatchQueue.main.async {
self?.imageView.image = UIImage(data: data!)
}
}
downloadTask.resume()
}