Cómo usar NSCache

121

¿Alguien puede dar un ejemplo sobre cómo usar NSCachepara almacenar en caché una cadena? ¿O alguien tiene un enlace a una buena explicación? Parece que no puedo encontrar ninguna ...

Thizzer
fuente
77
A pesar de ver una gran cantidad de cacao, nunca he oído hablar de NSCache. ¡Buena pregunta!
Nektarios
Creé una versión iterable de NSCache, aquí. Siéntase libre de contribuir: github.com/gregkrsak/GKCache
Greg M. Krsak

Respuestas:

134

Lo usas de la misma manera que lo harías NSMutableDictionary. La diferencia es que cuando NSCachedetecta una presión de memoria excesiva (es decir, está almacenando demasiados valores en caché), liberará algunos de esos valores para hacer espacio.

Si puede recrear esos valores en tiempo de ejecución (descargándolos de Internet, haciendo cálculos, lo que sea), entonces NSCachepuede satisfacer sus necesidades. Si los datos no se pueden volver a crear (por ejemplo, es una entrada del usuario, es urgente, etc.), entonces no debe almacenarlos en un NSCachearchivo porque se destruirá allí.

Ejemplo, sin tener en cuenta la seguridad del hilo:

// Your cache should have a lifetime beyond the method or handful of methods
// that use it. For example, you could make it a field of your application
// delegate, or of your view controller, or something like that. Up to you.
NSCache *myCache = ...;
NSAssert(myCache != nil, @"cache object is missing");

// Try to get the existing object out of the cache, if it's there.
Widget *myWidget = [myCache objectForKey: @"Important Widget"];
if (!myWidget) {
    // It's not in the cache yet, or has been removed. We have to
    // create it. Presumably, creation is an expensive operation,
    // which is why we cache the results. If creation is cheap, we
    // probably don't need to bother caching it. That's a design
    // decision you'll have to make yourself.
    myWidget = [[[Widget alloc] initExpensively] autorelease];

    // Put it in the cache. It will stay there as long as the OS
    // has room for it. It may be removed at any time, however,
    // at which point we'll have to create it again on next use.
    [myCache setObject: myWidget forKey: @"Important Widget"];
}

// myWidget should exist now either way. Use it here.
if (myWidget) {
    [myWidget runOrWhatever];
}
Jonathan Grynspan
fuente
1
¿Cómo instanciar el objeto NSCache? Parece que pierdo toda la información almacenada en caché cada vez que ejecuto la aplicación. Yo suelo; [[NSCache alloc] init]
Thizzer
17
No es un caché permanente en el disco. Solo está en la memoria, así que sí, se destruye cada vez que su aplicación deja de funcionar.
Jonathan Grynspan
¿Se mantiene este caché cuando la aplicación ingresa al backgruond? (es decir, después applicationDidEnterBackground)
barfoon
Si la aplicación no finaliza y el NSCacheobjeto no se desasigna, sí, permanecerá en la memoria. Sin embargo, su contenido puede estar sujeto a sacrificio.
Jonathan Grynspan
3
No. Una afirmación afirma que algo es verdadero, es decir, que se espera que la declaración interna sea verdadera. Estamos afirmando que la asignación y / o creación del objeto fue exitosa.
Jonathan Grynspan
19
@implementation ViewController
{    
    NSCache *imagesCache;    
}


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


// How to save and retrieve NSData into NSCache
NSData *imageData = [imagesCache objectForKey:@"KEY"];
[imagesCache setObject:imageData forKey:@"KEY"];
Gabriel.Massana
fuente
3
Si. Guardar: [imagesDictionary setObject: imageData forKey: @ "KEY"]; recuperar: NSData * imageData = [imagesCache objectForKey: @ "KEY"];
Gabriel.Massana
2
guardar datos en chache: [imagesCache setObject: imageData forKey: @ "KEY"];
kas-kad
1
Acabo de editar la publicación modificada: imagesDictionary for imagesCache. Thx
Gabriel.Massana
¿Un ejemplo rápido equivalente?
Jasper
9

Código de muestra para almacenar en caché una cadena usando NSCache en Swift:

var cache = NSCache()
cache.setObject("String for key 1", forKey: "Key1")
var result = cache.objectForKey("Key1") as String
println(result) // Prints "String for key 1"

Para crear una única instancia de NSCache en toda la aplicación (un singleton), puede extender fácilmente NSCache para agregar una propiedad sharedInstance. Simplemente ponga el siguiente código en un archivo llamado algo así como NSCache + Singleton.swift:

import Foundation

extension NSCache {
    class var sharedInstance : NSCache {
        struct Static {
            static let instance : NSCache = NSCache()
        }
        return Static.instance
    }
}

Luego puede usar el caché en cualquier lugar de la aplicación:

NSCache.sharedInstance.setObject("String for key 2", forKey: "Key2")
var result2 = NSCache.sharedInstance.objectForKey("Key2") as String
println(result2) // Prints "String for key 2"
PointZeroTwo
fuente
3
¿Sabes cómo implementar esto en Swift 3?
Andy
3
Esto debería funcionar: class Cache: NSCache<AnyObject, AnyObject> { static let shared = NSCache<AnyObject, AnyObject>() private override init() { super.init() } }
AmitaiB
6

Proyecto de muestra Agregue el archivo CacheController.h y .m del proyecto de muestra a su proyecto. En la clase donde desea almacenar datos en caché, coloque el siguiente código.

[[CacheController storeInstance] setCache:@"object" forKey:@"objectforkey" ];

puedes configurar cualquier objeto usando esto

[[CacheController storeInstance] getCacheForKey:@"objectforkey" ];

para recuperar

Importante: la clase NSCache incorpora varias políticas de eliminación automática. si desea almacenar en caché los datos de forma permanente o si desea eliminar los datos almacenados en caché en un momento específico, consulte esta respuesta .

Ajumal
fuente
1

¿No deberían los objetos en caché implementar el protocolo NSDiscardableContent?

De la referencia de clase NSCache: Un tipo de datos común almacenado en objetos NSCache es un objeto que implementa el protocolo NSDiscardableContent. Almacenar este tipo de objeto en un caché tiene beneficios, ya que su contenido puede descartarse cuando ya no se necesita, lo que ahorra memoria. De forma predeterminada, los objetos NSDiscardableContent en el caché se eliminan automáticamente del caché si se descarta su contenido, aunque esta política de eliminación automática se puede cambiar. Si un objeto NSDiscardableContent se coloca en la memoria caché, la memoria caché llama a discardContentIfPossible en él después de su eliminación.

Fénix
fuente
1
Puede implementar el protocolo NSDiscardableContent, pero esto no es obligatorio. Como parece, NSDiscardableContent siempre se elimina de NSCache cuando no hay más referencias. Los objetos que no sean el objeto NSDiscardableContent se almacenan en NSCache hasta que haya "memoria insuficiente" y NSCache se borre.
Thizzer