LoginSignup
20

More than 5 years have passed since last update.

Swift で NSCache を Generics にして便利に

Last updated at Posted at 2016-05-01

NSCache

イメージなどをファイルから読み込む、またはon the flyで処理して利用するにはちと重いデータなどは、一度処理して結果を NSCache に保存しておく事は TableView などの表示には有効です。

ところが、NSCache とのインターフェースは AnyObject なので、Swiftで使うときはいちいち as? MyObject とかキャストしなくてはなりません。

そこで、NSCache をラップして Generics で使えるようにしてみました。

ZCache.swift
import Foundation


class ZCache<T: AnyObject> {

    private var cache = NSCache()

    var delegate: NSCacheDelegate? {
        get { return self.delegate }
        set { self.cache.delegate = newValue }
    }

    var name: String {
        get { return self.cache.name }
        set { self.cache.name =  newValue }
    }

    func objectForKey(key: AnyObject) -> T? {
        return self.cache.objectForKey(key) as? T
    }

    func setObject(obj: T, forKey key: AnyObject) {
        self.cache.setObject(obj, forKey: key)
    }

    func setObject(obj: T, forKey key: AnyObject, cost g: Int) {
        self.cache.setObject(obj, forKey: key, cost: g)
    }

    func removeObjectForKey(key: AnyObject) {
        self.cache.removeObjectForKey(key)
    }

    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.evictsObjectsWithDiscardedContent = newValue }
    }

    // MARK: -

    subscript(key: AnyObject) -> T? {
        get { return self.cache.objectForKey(key) as? T }
        set {
            if let newValue = newValue {
                self.cache.setObject(newValue, forKey: key)
            }
            else {
                self.cache.removeObjectForKey(key)
            }
        }
    }

}

NSCache のすべてのメソッドをラップしていますので、オリジナルと同様に利用できるはずです。加えて subscript(key: AnyObject) でアクセスできるようにしてみました。その際、セッターは nil を設定した場合は、オブジェクトを remove しています。

generics で実装されていますので、毎回毎回キャストする必要はなく、Swift らしくコーディングを進めることができるのではないでしょうか?

利用例を紹介いたします。

var cache = ZCache<NSImage>()

cache["1"] = NSImage(named: "1") // assume there is!!
let image1 = cache["1"] // image

cache["1"] = nil
let image2 = cache["1"] // nil

コードは gist からも入手可能です。
https://gist.github.com/codelynx/29b2c2a36d290cec58a009ef712f33b0

それでは、みなさん、Have a happy coding!!

関連情報

Swift で Key や Value に弱参照が使える Dictionary 的な方法を考える
http://qiita.com/codelynx/items/27b8dd8c3ac49f6316ef

環境情報

swift --version
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)

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
20