Jak korzystać z NSCache

121

Czy ktoś może podać przykład, jak używać NSCachedo buforowania ciągu? Czy ktoś ma link do dobrego wyjaśnienia? Nie mogę znaleźć żadnego ...

Thizzer
źródło
7
Pomimo zobaczenia ogromnej ilości kakao nigdy nie słyszałem o NSCache. Dobre pytanie!
Nektarios
Stworzyłem tutaj iterowalną wersję NSCache. Zapraszam do współtworzenia: github.com/gregkrsak/GKCache
Greg M. Krsak

Odpowiedzi:

134

Używasz go w taki sam sposób, jak byś używał NSMutableDictionary. Różnica polega na tym, że gdy NSCachewykryje nadmierne obciążenie pamięci (tj. Buforuje zbyt wiele wartości), zwolni niektóre z tych wartości, aby zrobić miejsce.

Jeśli możesz odtworzyć te wartości w czasie wykonywania (pobierając je z Internetu, wykonując obliczenia, cokolwiek), NSCachemoże to odpowiadać Twoim potrzebom. Jeśli danych nie można odtworzyć (np. Są to dane wprowadzone przez użytkownika, są wrażliwe na czas itp.), Nie należy ich przechowywać w pliku, NSCacheponieważ zostaną tam zniszczone.

Przykład bez uwzględnienia bezpieczeństwa wątków:

// 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
źródło
1
jak utworzyć wystąpienie obiektu NSCache? Wydaje mi się, że tracę wszystkie informacje z pamięci podręcznej za każdym razem, gdy uruchamiam aplikację. Używam; [[NSCache assign] init]
Thizzer
17
To nie jest stała pamięć podręczna na dysku. Jest tylko w pamięci, więc tak, jest niszczony za każdym razem, gdy aplikacja przestaje działać.
Jonathan Grynspan
Czy ta pamięć podręczna jest utrzymywana, gdy aplikacja przechodzi do backgruond? (czyli po applicationDidEnterBackground)
barfoon
Jeśli aplikacja nie zostanie zakończona, a NSCacheobiekt nie zostanie zwolniony, to tak, pozostanie w pamięci. Jednak jego zawartość może nadal podlegać ubojowi.
Jonathan Grynspan,
3
Nie. Stwierdzenie twierdzi, że coś jest prawdą, tj. Że oczekuje się, że stwierdzenie wewnątrz będzie prawdziwe. Oświadczamy, że przypisanie i / lub utworzenie obiektu zakończyło się pomyślnie.
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
źródło
3
Tak. Zapisz: [imagesDictionary setObject: imageData forKey: @ "KEY"]; retrieve: NSData * imageData = [imagesCache objectForKey: @ "KEY"];
Gabriel.Massana
2
zapisz dane do chache: [imagesCache setObject: imageData forKey: @ "KEY"];
kas-kad
1
Właśnie zredagowałem zmieniony post: imagesDictionary for imagesCache. Dzięki
Gabriel.Massana
Równoważny szybki przykład?
Jasper
9

Przykładowy kod do buforowania ciągu przy użyciu NSCache w języku 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"

Aby utworzyć pojedyncze wystąpienie NSCache dla całej aplikacji (singleton), możesz łatwo rozszerzyć NSCache, aby dodać właściwość sharedInstance. Po prostu umieść następujący kod w pliku o nazwie podobnej do NSCache + Singleton.swift:

import Foundation

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

Następnie możesz użyć pamięci podręcznej w dowolnym miejscu aplikacji:

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
źródło
3
czy wiesz, jak to zaimplementować w Swift 3?
Andy
3
To powinno działać: class Cache: NSCache<AnyObject, AnyObject> { static let shared = NSCache<AnyObject, AnyObject>() private override init() { super.init() } }
AmitaiB
6

przykładowy projekt Dodaj plik CacheController.h i .m z przykładowego projektu do projektu. W klasie, w której chcesz przechowywać dane w pamięci podręcznej, umieść poniższy kod.

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

możesz ustawić dowolny obiekt za pomocą tego

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

odzyskać

Ważne: Klasa NSCache zawiera różne zasady automatycznego usuwania. jeśli chcesz buforować dane na stałe lub chcesz usunąć dane z pamięci podręcznej w określonym czasie, zobacz tę odpowiedź .

Ajumal
źródło
1

Czy buforowane obiekty nie powinny implementować protokołu NSDiscardableContent?

Z opisu klasy NSCache: Typowym typem danych przechowywanym w obiektach NSCache jest obiekt implementujący protokół NSDiscardableContent. Przechowywanie tego typu obiektu w pamięci podręcznej ma zalety, ponieważ jego zawartość można wyrzucić, gdy nie jest już potrzebna, oszczędzając w ten sposób pamięć. Domyślnie obiekty NSDiscardableContent w pamięci podręcznej są automatycznie usuwane z pamięci podręcznej, jeśli ich zawartość zostanie odrzucona, chociaż tę zasadę automatycznego usuwania można zmienić. Jeśli obiekt NSDiscardableContent zostanie umieszczony w pamięci podręcznej, pamięć podręczna wywoła na nim discardContentIfPossible po jego usunięciu.

Feniks
źródło
1
Możesz zaimplementować protokół NSDiscardableContent, ale nie jest to wymagane. Jak się wydaje, NSDiscardableContent jest zawsze usuwana z NSCache, gdy nie ma już odwołań. Obiekty inne niż obiekt NSDiscardableContent są przechowywane w NSCache do momentu, gdy „pamięć jest napięta” i nie zostanie wyczyszczona pamięć NSCache.
Thizzer