読者です 読者をやめる 読者になる 読者になる

ninjinkun's diary

ninjinkunの日記

iOS組み込みのキャッシュモジュールNSCacheについて発表しました

NSCacheというキャッシュモジュールについて第43回Cocoa関西で発表してきました。

NSCacheの特徴

  • スレッドセーフ
    • NSDictionaryのように手動でロックする必要がない
  • 格納オブジェクトの上限を決められる
    • 溢れたら自動破棄
    • iOSのようなメモリ制約の厳しい環境に最適
  • NSDictionaryに似たインターフェイス
  • Mac OS 10.6 / iOS 4.0以上で使える

具体例としては、ダウンロードした画像をオンメモリにキャッシュする際等にとても有用だと思います。同じような機能を提供してくれるOSSのモジュールは見たことがあるのですが(例えばnimbusに含まれているNIMemoryCache)こちらはOS組み込みなので手軽に使えます。

発表資料


サンプルコード

Twitter及びInstagramの画像をロードしてデモするサンプルコードは以下です。それぞれの機能を動かすには、組み込みTwitterの連携設定とInstagramのアプリケーションキーが必要になります。
http://github.com/ninjinkun/NSCacheTest

おまけ

発表後の質疑応答で、キャッシュの破棄は基本的にLRUで行われていそうだという部分に、コストを入れた場合は別のアルゴリズムで破棄が行われるのではないかという意見が出ました。一応追試をしてみましたが、コストを入れた場合でもLRUのようでした。追試のコードは以下の通りです。

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSInteger size = 1024;
        NSCache *cache = [[NSCache alloc] init];        
        
        for (int i = 0; i < 100; i++) {
            NSData *data = [NSData dataWithBytes:malloc(size) length:size];
            cache.totalCostLimit = 1000;
            [cache objectForKey:[NSNumber numberWithInt:10]]; // 途中で10にアクセスしてみる
            [cache setObject:data forKey:[NSNumber numberWithInt:i] cost:i];                        
        }
        
        for (int i = 0; i < 100; i++) {
            NSData *data = [cache objectForKey:[NSNumber numberWithInt:i]];            
            if (data) {
                NSLog(@"has data #%d", i);
            }
        }
    }
    return 0;
}

has data #10
has data #90
has data #91
has data #92
has data #93
has data #94
has data #95
has data #96
has data #97
has data #98
has data #99

3/26 16:50追記

id:KishikawaKatsumi さんが参考になる感じの使い方をつぶやかれていたので、以下に引用します。転載許可ありがとうございます! > id:KishikawaKatsumiさん


3/30 12:10追記

3/27にid:KishikawaKatsumiさんの画像キャッシュとダウンローダーについての記事が公開されていました。反応遅れてすみません…。だいぶ参考になる内容です。
ダウンロードした画像をキャッシュするクラスの設計と実装について - 24/7 twenty-four seven

2013/12/11 追記

画像の取得はSDWebImageに任せると良いと思います。このモジュールでも内部でNSCacheが使われています。