17
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Swift] NSCacheをシングルトンにして使う

Last updated at Posted at 2018-06-21

画像を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のシングルトンを作ってみましょう

コードは下のようになります。

cache.swift
final class Cache: NSCache<AnyObject, AnyObject> {
    static let sharedInstance = Cache()
    private override func init() {
       // 特に何もする必要なし
    }
}

これだけでNSCacheのシングルトンを表現することができます
ポイントは

  1. finalにすること
  2. 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()
}

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?