NSCache no está desalojando datos

NSCache es una herramienta poco utilizada que realmente parece bastante útil. Creé un experimento simple para ver cómo funciona y parece que no desecha automáticamente datos en situaciones de poca memory (¡o estoy haciendo algo mal!)

- (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* dataRecovenetworkingFromCache = [_testCache objectForKey:@"original_Data"]; if (dataRecovenetworkingFromCache) { NSLog(@"Original data is ok"); } else { NSLog(@"Original data is missing (purged from cache)"); } } 

Entonces ejecuté la aplicación en el simulador y pegué el button varias veces, pero no se desalojaron elementos … La aplicación finalmente se estrelló:

 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 

Desde el documento (mina Emphasis): la class NSCache incorpora varias políticas de eliminación automática, que garantizan que no use demasiada memory del sistema. El sistema realiza automáticamente estas políticas si otras aplicaciones necesitan memory. Cuando se invocan, estas políticas eliminan algunos elementos del caching, lo que minimiza su huella de memory.

Apple no afirma que la memory se liberará en la advertencia de memory: en mi experiencia, el caching se purga con mayor frecuencia cuando la aplicación pasa a segundo plano o cuando agrega elementos más grandes.

Aquí se cita docs …

La class NSCache incorpora varias políticas de eliminación automática, que aseguran que no utilice demasiada memory del sistema. El sistema realiza automáticamente estas políticas si otras aplicaciones necesitan memory. Cuando se invocan, estas políticas eliminan algunos elementos del caching, lo que minimiza su huella de memory.

… como puedes ver, indica que elimina algunos elementos, no todos los elementos. Depende de las políticas internas de NSCache , la memory disponible, el estado del dispositivo, etc. No debe preocuparse por estas políticas.

Puedes controlarlos con countLimit , totalCostLimit y puedes agregar objects con el costo, mira setObject:forKey:cost:

También puedes desalojar objects por ti mismo. Agregue la NSDiscardableContent protocolo NSDiscardableContent a sus objects y setEvictsObjectsWithDiscardedContent : a YES .

Estoy usando esa class también. Tenga en count que la documentation indica que NSCache está vinculado al sistema operativo y que probablemente tenga acceso a información de memory en el interior del sistema operativo. La advertencia de memory es solo eso: simplemente envía una advertencia de memory a appDelegate / viewControllers.

Si realmente quiere probar su código, es probable que necesite un modo de testing donde empiece a almacenar mucha memory (creando una gran pérdida, por así decirlo). Es posible que necesites plotr esto en pedazos durante cada runloop principal, por lo que el sistema operativo tiene la oportunidad de ver que la memory va hacia abajo (tengo una aplicación que mastica mucha memory, y lo hace tan rápido en el 3GS que acaba de ser asesinado nunca habiendo recibido una advertencia de memory.