Comment utiliser NSCache

121

Quelqu'un peut-il donner un exemple sur la façon d'utiliser NSCachepour mettre en cache une chaîne? Ou quelqu'un a un lien vers une bonne explication? Je n'arrive pas à en trouver ...

Thizzer
la source
7
Malgré une énorme quantité de Cocoa, je n'ai jamais entendu parler de NSCache. Bonne question!
Nektarios
J'ai créé une version itérative de NSCache, ici. N'hésitez pas à y contribuer: github.com/gregkrsak/GKCache
Greg M. Krsak

Réponses:

134

Vous l'utilisez de la même manière que vous l'utiliseriez NSMutableDictionary. La différence est que lorsque NSCachedétecte une pression mémoire excessive (c'est-à-dire qu'il met en cache trop de valeurs), il libère certaines de ces valeurs pour faire de la place.

Si vous pouvez recréer ces valeurs au moment de l'exécution (en les téléchargeant sur Internet, en effectuant des calculs, peu importe), cela NSCachepeut répondre à vos besoins. Si les données ne peuvent pas être recréées (par exemple, elles sont entrées par l'utilisateur, elles sont sensibles au temps, etc.), vous ne devez pas les stocker dans un NSCachecar elles y seront détruites.

Exemple, sans prise en compte de la sécurité des threads:

// 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
la source
1
comment instancier l'objet NSCache? Il me semble perdre toutes les informations mises en cache à chaque fois que je lance l'application. J'utilise; [[NSCache alloc] init]
Thizzer
17
Ce n'est pas un cache permanent sur disque. Il est uniquement en mémoire, donc oui, il est détruit chaque fois que votre application cesse de fonctionner.
Jonathan Grynspan
Ce cache est-il conservé après que l'application entre dans le backgruond? (ie après applicationDidEnterBackground)
barfoon
Si l'application n'est pas terminée et que l' NSCacheobjet n'est pas désalloué, alors oui, il restera en mémoire. Cependant, son contenu peut encore être abattu.
Jonathan Grynspan
3
Non. Une assertion affirme que quelque chose est vrai, c'est-à-dire que la déclaration à l'intérieur est censée être vraie. Nous affirmons que l'attribution et / ou la création d'objet a réussi.
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
la source
3
Oui. Enregistrer: [imagesDictionary setObject: imageData forKey: @ "KEY"]; récupérer: NSData * imageData = [imagesCache objectForKey: @ "KEY"];
Gabriel.Massana
2
enregistrer les données à chache: [imagesCache setObject: imageData forKey: @ "KEY"];
kas-kad
1
Je viens de modifier le message modifié: imagesDictionary pour imagesCache. Thx
Gabriel.Massana
Un exemple rapide équivalent?
Jasper
9

Exemple de code pour la mise en cache d'une chaîne à l'aide de NSCache dans 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"

Pour créer une seule instance de NSCache à l'échelle de l'application (un singleton), vous pouvez facilement étendre NSCache pour ajouter une propriété sharedInstance. Mettez simplement le code suivant dans un fichier appelé quelque chose comme NSCache + Singleton.swift:

import Foundation

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

Vous pouvez ensuite utiliser le cache n'importe où dans l'application:

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
la source
3
savez-vous comment mettre en œuvre cela dans swift 3?
Andy
3
Cela devrait fonctionner: class Cache: NSCache<AnyObject, AnyObject> { static let shared = NSCache<AnyObject, AnyObject>() private override init() { super.init() } }
AmitaiB
6

exemple de projet Ajoutez le fichier CacheController.h et .m de l'exemple de projet à votre projet. Dans la classe où vous souhaitez mettre en cache les données, mettez le code ci-dessous.

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

vous pouvez définir n'importe quel objet en utilisant ceci

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

récupérer

Important: la classe NSCache incorpore diverses stratégies de suppression automatique. si vous souhaitez mettre en cache les données de manière permanente ou si vous souhaitez supprimer les données mises en cache à un moment donné, consultez cette réponse .

Ajumal
la source
1

Les objets mis en cache ne devraient-ils pas implémenter le protocole NSDiscardableContent?

À partir de la référence de classe NSCache: Un type de données commun stocké dans les objets NSCache est un objet qui implémente le protocole NSDiscardableContent. Le stockage de ce type d'objet dans un cache présente des avantages, car son contenu peut être supprimé lorsqu'il n'est plus nécessaire, économisant ainsi de la mémoire. Par défaut, les objets NSDiscardableContent dans le cache sont automatiquement supprimés du cache si leur contenu est ignoré, bien que cette stratégie de suppression automatique puisse être modifiée. Si un objet NSDiscardableContent est placé dans le cache, le cache appelle discardContentIfPossible sur celui-ci lors de sa suppression.

Phénix
la source
1
Vous pouvez implémenter le protocole NSDiscardableContent mais ce n'est pas obligatoire. Comme il semble, NSDiscardableContent est toujours supprimé de NSCache lorsqu'il n'y a plus de références. Les objets autres que l'objet NSDiscardableContent sont stockés dans NSCache jusqu'à ce qu'il y ait «mémoire insuffisante» et NSCache va être effacé.
Thizzer