メモリキャッシュとありますが、ヘッダから分かる通りNSMutableDictioaryです。
NSCacheよりしぶといメモリキャッシュが欲しかったので、頭の体操をしながらつくりました。

ISMemoryCache

特徴

LRU的な実装ではなく、参照カウントの有無で破棄するオブジェクトを決めます。
どこかから参照がある限りは生き残り続けるしぶといメモリキャッシュです。

  • removeUnretainedObjectsを呼ぶと参照がないオブジェクトを調べて破棄する。
  • UIApplicationDidReceiveMemoryWarningNotificationremoveUnretainedObjectsを実行。

具体的には、以下の実行後に[cache objectForKey:@"key"]NSObjectを返しますが、

NSObject *retainedObject = [[NSObject alloc] init];
@autoreleasepool {
    [cache setObject:retainedObject forKey:@"key"];
}
[cache removeUnretainedObjects];

以下の実行後にはnilを返すという感じです。 

@autoreleasepool {
    NSObject *unretainedObject = [[NSObject alloc] init];
    [cache setObject:unretainedObject forKey:@"key"];
}
[cache removeUnretainedObjects];

使い方

保持 objectivec [[ISMemoryCache sharedCache] setObject:object forKey:@"key"];

読み出し objectivec [[ISMemoryCache sharedCache] objectForKey:@"key"];

使われていないオブジェクトを破棄 objectivec [[ISMemoryCache sharedCache] removeUnretainedObjects];

参照があるかどうかの判定方法

自分の強参照を外しても生き残っていれば、他でも使われているということです。

- (void)removeUnretainedObjects
{
    for (NSString *key in [self allKeys]) {
        __weak id wobject;
        
        @autoreleasepool {
            wobject = [self objectForKey:key];
            [self removeObjectForKey:key];
        }
        
        if (wobject) {
            [self setObject:wobject forKey:key];
        }
    }
}

NSDictionaryのサブクラス化

NSDictionaryはクラスクラスタなのでサブクラス化の作法がちょっと変わっています。
今回は面倒だったので内部にNSMutableDictionaryを持って適宜プロキシする感じにしました。
適宜というのはNSDictionaryのドキュメントに書かれている以下のメソッドが呼ばれた時です。

// NSDictionary
- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys;
- (NSUInteger)count;
- (id)objectForKey:(id)key;
- (NSEnumerator *)keyEnumerator;

// NSMutableDictionary
- (void)setObject:(id)object forKey:(id <NSCopying>)key;
- (void)removeObjectForKey:(id)key;