しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

NSCacheについて調べてみる

NSCacheについて調べてみました。

NSCacheとは

Foundation Frameworkの中の一つのクラス。
キャッシュの保存と取得ができるクラスです。
NSDictionaryに似ているのですが、NSDictionaryと違ってスレッドセーフになっています。

NSCacheクラスの中身

下がNSCacheクラスの中身です、非常にシンプルになっています。

class NSCache : NSObject {
    
    var name: String
    
    unowned(unsafe) var delegate: NSCacheDelegate?
    
    func objectForKey(key: AnyObject) -> AnyObject?
    func setObject(obj: AnyObject, forKey key: AnyObject) // 0 cost
    func setObject(obj: AnyObject, forKey key: AnyObject, cost g: Int)
    func removeObjectForKey(key: AnyObject)
    
    func removeAllObjects()
    
    var totalCostLimit: Int // limits are imprecise/not strict
    var countLimit: Int // limits are imprecise/not strict
    var evictsObjectsWithDiscardedContent: Bool
}

protocol NSCacheDelegate : NSObjectProtocol {
    
    optional func cache(cache: NSCache, willEvictObject obj: AnyObject)
}

NSCacheの使い方

下のようにsetObjectを使って値をセットして、objectForKeyで値を取得できます。
objectForKeyは値をセットしてない場合はnilが返ってきます。
アプリを再起動するとキャッシュもクリアされます。

let cache = NSCache()

var value = cache.objectForKey("key")
NSLog("\(value)")

cache.setObject("value", forKey: "key")

value = cache.objectForKey("key")
NSLog("\(value)")

NSCache同士は値を共有していないので、別NSCacheインスタンスの値を取得できません。

NSCache().setObject("value", forKey: "key")
let value = NSCache().objectForKey("key")
NSLog("\(value)") // → nil

キャッシュの削除はremoveObjectForKeyremoveAllObjectsが使えます。

let cache = NSCache()
cache.removeObjectForKey("key")
cache.removeAllObjects()

キャッシュには名前を付ける事ができます。

let cache = NSCache()
cache.name = "MyCache"

delegateをセットするとキャッシュが削除されるタイミングでdelegateメソッドが呼ばれます。
キャッシュがいつ削除されたか知りたい時に使うと便利そうです。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
    let cache = NSCache()
    cache.delegate = self
    cache.setObject("value", forKey: "key")
    NSLog("1")
    cache..removeAllObjects()
    NSLog("2")

    return true
}

func cache(cache: NSCache, willEvictObject obj: AnyObject) {
    NSLog("Called")
}

キャッシュには保存個数をセットする事ができます。
下の場合は2個を超えた数(3個以上)保存された時に一番使われていないものが削除されます。

let cache = NSCache()
cache.countLimit = 2

最後にアクセスしたキャッシュが消えるので、下の例ではkey2が消されます。

let cache = NSCache()
cache.countLimit = 2

cache.setObject("1", forKey: "key1")
print(cache.objectForKey("key1"))
cache.setObject("2", forKey: "key2")
print(cache.objectForKey("key1"))
cache.setObject("3", forKey: "key3")
print(cache.objectForKey("key1"))
cache.setObject("4", forKey: "key4")
print(cache.objectForKey("key1"))

あとはcostという概念もあるようです。

let cache = NSCache()

cache.totalCostLimit = 10
cache.setObject("1", forKey: "key", cost: 1)

まとめ

NSCacheは簡単ながらもとても使いやすそうな印象を受けました。
唯一キャッシュの有効期間をセットできないのが残念ですがそこ以外はとても便利そうです。