Как использовать NSCache

121

Может кто-нибудь привести пример того, как использовать NSCacheдля кеширования строки? Или у кого-нибудь есть ссылка на хорошее объяснение? Кажется, я не могу найти ...

Thizzer
источник
7
Несмотря на то, что я видел огромное количество какао, я никогда не слышал о NSCache. Хороший вопрос!
Nektarios
Я создал итеративную версию NSCache здесь. Не стесняйтесь вносить свой вклад в это: github.com/gregkrsak/GKCache
Грег М. Крсак

Ответы:

134

Вы используете его так же, как и раньше NSMutableDictionary. Разница в том, что при NSCacheобнаружении чрезмерной нагрузки на память (т. Е. Кэширование слишком большого количества значений) он освобождает некоторые из этих значений, чтобы освободить место.

Если вы можете воссоздать эти значения во время выполнения (путем загрузки из Интернета, выполнения расчетов и т. Д.), Это NSCacheможет удовлетворить ваши потребности. Если данные не могут быть воссозданы (например, это пользовательский ввод, они чувствительны ко времени и т. Д.), Вы не должны хранить их в папке, NSCacheпотому что они будут там уничтожены.

Пример без учета потоковой безопасности:

// 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];
}
Джонатан Гринспан
источник
1
как создать экземпляр объекта NSCache? Кажется, я теряю всю кешированную информацию каждый раз, когда запускаю приложение. Я использую; [[NSCache alloc] init]
Thizzer
17
Это не постоянный кеш на диске. Он находится только в памяти, поэтому да, он уничтожается каждый раз, когда ваше приложение перестает работать.
Джонатан Гринспан
Поддерживается ли этот кеш после того, как приложение переходит в фоновый режим? (т.е. после applicationDidEnterBackground)
barfoon
Если приложение не завершено и NSCacheобъект не освобожден, то да, он останется в памяти. Однако его содержимое может быть удалено.
Джонатан Гринспан
3
Нет. Утверждение утверждает, что что-то истинно, т. Е. Что утверждение внутри должно быть истинным. Мы утверждаем, что назначение и / или создание объекта было успешным.
Джонатан Гринспан
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
источник
3
Да. Сохранить: [imagesDictionary setObject: imageData forKey: @ "KEY"]; получить: NSData * imageData = [imagesCache objectForKey: @ "KEY"];
Габриэль Массана
2
сохранить данные в chache: [imagesCache setObject: imageData forKey: @ "KEY"];
kas-kad
1
Я только что отредактировал сообщение изменено: imagesDictionary для imagesCache. Thx
Gabriel.Massana
Эквивалентный быстрый пример?
Джаспер
9

Пример кода для кеширования строки с использованием NSCache в 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"

Чтобы создать единый экземпляр NSCache для всего приложения (синглтон), вы можете легко расширить NSCache, добавив свойство sharedInstance. Просто поместите следующий код в файл под названием NSCache + Singleton.swift:

import Foundation

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

Затем вы можете использовать кеш в любом месте приложения:

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
источник
3
вы знаете, как реализовать это в Swift 3?
Энди
3
Это должно работать: class Cache: NSCache<AnyObject, AnyObject> { static let shared = NSCache<AnyObject, AnyObject>() private override init() { super.init() } }
AmitaiB
6

образец проекта Добавьте файл CacheController.h и .m из образца проекта в свой проект. В классе, в котором вы хотите кэшировать данные, поместите приведенный ниже код.

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

вы можете установить любой объект с помощью этого

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

извлечь

Важно: класс NSCache включает в себя различные политики автоматического удаления. если вы хотите кэшировать данные на постоянной основе или хотите удалить кешированные данные в определенное время, см. этот ответ .

Ajumal
источник
1

Разве кэшированные объекты не должны реализовывать протокол NSDiscardableContent?

Из справочника по классу NSCache: Общий тип данных, хранящийся в объектах NSCache, - это объект, реализующий протокол NSDiscardableContent. Хранение этого типа объекта в кэше имеет преимущества, потому что его содержимое может быть удалено, когда оно больше не нужно, тем самым экономя память. По умолчанию объекты NSDiscardableContent в кэше автоматически удаляются из кеша, если их содержимое отбрасывается, хотя эту политику автоматического удаления можно изменить. Если объект NSDiscardableContent помещается в кеш, кеш вызывает для него discardContentIfPossible после его удаления.

Феникс
источник
1
Вы можете реализовать протокол NSDiscardableContent, но это не обязательно. Кажется, что NSDiscardableContent всегда удаляется из NSCache, когда больше нет ссылок. Объекты, отличные от объекта NSDiscardableContent, хранятся в NSCache до тех пор, пока не будет «недостаточно памяти» и NSCache не будет очищен.
Thizzer