11

NSCacheはめったに使用されないツールであり、実際には非常に便利に見えます。簡単な実験を作成して、それがどのように機能するかを確認しました。メモリが少ない状況ではデータが自動削除されないようです(または何か間違ったことをしています!)

- (void)viewDidLoad
{
    _testCache = [[NSCache alloc] init];

    // Allocate 600 MB of zeros and save to NSCache
    NSMutableData* largeData = [[NSMutableData alloc] init];
    [largeData setLength:1024 * 1024 * 600]; 
    [_testCache setObject:largeData forKey:@"original_Data"];
}

- (IBAction)buttonWasTapped:(id)sender {

    // Allocate & save to cache 300 MB each time the button is pressed
    NSMutableData* largeData = [[NSMutableData alloc] init];
    [largeData setLength:1024 * 1024 * 300]; 
    static int count = 2;
    NSString* key = [NSString stringWithFormat:@"test_data_%d", count++];
    [_testCache setObject:largeData forKey:key];

    NSMutableData* dataRecoveredFromCache = [_testCache objectForKey:@"original_Data"];

    if (dataRecoveredFromCache) {
        NSLog(@"Original data is ok");
    } else {
        NSLog(@"Original data is missing (purged from cache)");
    }
}

そこで、シミュレーターでアプリを実行し、ボタンを数回テープで貼りましたが、アイテムが削除されませんでした...アプリは最終的にクラッシュしました。

2012-07-17 14:19:36.877 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:37.365 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:37.861 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:38.341 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:38.821 NSCacheTest[15302:f803] Data is ok
NSCacheTest(15302,0xac0942c0) malloc: *** mmap(size=393216000) failed (error code=12)
*** error: can't allocate region
4

3 に答える 3

15

ドキュメント(Emphasis mine)から:NSCacheクラスには、システムのメモリを使いすぎないようにするさまざまな自動削除ポリシーが組み込まれています。他のアプリケーションでメモリが必要な場合、システムはこれらのポリシーを自動的に実行します。これらのポリシーが呼び出されると、キャッシュから一部のアイテムが削除され、メモリフットプリントが最小限に抑えられます。

Appleは、メモリ警告でメモリが解放されるとは述べていません-私の経験では、アプリがバックグラウンドに移行したとき、またはより大きな要素を追加したときに、キャッシュはほとんどの場合パージされます。

于 2012-07-17T11:25:26.697 に答える
7

ここに引用されたドキュメントがあります...

NSCacheクラスには、システムのメモリを使いすぎないようにするさまざまな自動削除ポリシーが組み込まれています。他のアプリケーションでメモリが必要な場合、システムはこれらのポリシーを自動的に実行します。これらのポリシーが呼び出されると、キャッシュから一部のアイテムが削除され、メモリフットプリントが最小限に抑えられます。

...ご覧のとおり、すべてのアイテムではなく、一部のアイテムが削除されると記載されています。これは、NSCache内部ポリシー、使用可能なメモリ、デバイスのステータスなどによって異なります。これらのポリシーについて心配する必要はありません。

countLimit、プロパティを使用してそれらを制御できtotalCostLimit、コストを使用してオブジェクトを追加できます。を見てくださいsetObject:forKey:cost:

また、自分でオブジェクトを削除することもできます。NSDiscardableContentオブジェクトにプロトコル実装を追加し、 setEvictsObjectsWithDiscardedContent:を。に追加しますYES

于 2012-07-17T11:21:38.337 に答える
1

私もそのクラスを使っています。ドキュメントには、NSCacheがOSに関連付けられており、おそらくOSの奥深くにあるメモリ情報にアクセスできると記載されていることに注意してください。メモリ警告はまさにそれです-それは単にメモリ警告をappDelegate/viewControllersに送信します。

本当にコードをテストしたい場合は、おそらく、大量のメモリのマロックを開始するテストモードが必要になります(いわば巨大なリークが発生します)。各メインランループ中にこれをチャンクに分割する必要があるかもしれないので、OSはメモリがダウンしているのを見る機会があります(私はたくさんのメモリを噛み砕くアプリを持っています、そしてそれはちょうど殺される3GSでそれをとても速くしますメモリ警告を受け取ったことはありません。

于 2012-07-17T11:31:25.560 に答える