How to use NSCache

62,224

Solution 1

You use it the same way you would use NSMutableDictionary. The difference is that when NSCache detects excessive memory pressure (i.e. it's caching too many values) it will release some of those values to make room.

If you can recreate those values at runtime (by downloading from the Internet, by doing calculations, whatever) then NSCache may suit your needs. If the data cannot be recreated (e.g. it's user input, it is time-sensitive, etc.) then you should not store it in an NSCache because it will be destroyed there.

Example, not taking thread safety into account:

// 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];
}

Solution 2

@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"];

Solution 3

Sample code for caching a string using NSCache in 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"

To create a single app-wide instance of NSCache (a singleton), you can easily extend NSCache to add a sharedInstance property. Just put the following code in a file called something like NSCache+Singleton.swift:

import Foundation

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

You can then use the cache anywhere in the app:

NSCache.sharedInstance.setObject("String for key 2", forKey: "Key2")
var result2 = NSCache.sharedInstance.objectForKey("Key2") as String
println(result2) // Prints "String for key 2"

Solution 4

sample Project Add CacheController.h and .m file from the sample project to your project. In class where you want to cache data , put the below code.

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

you can set any object using this

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

to retrive

Important: The NSCache class incorporates various auto-removal policies. if you want cache the data for permanent or you want to remove cached data in a specific time see this answer.

Solution 5

Shouldn't the cached objects implement the NSDiscardableContent protocol?

From the NSCache class reference: A common data type stored in NSCache objects is an object that implements the NSDiscardableContent protocol. Storing this type of object in a cache has benefits, because its content can be discarded when it is not needed anymore, thus saving memory. By default, NSDiscardableContent objects in the cache are automatically removed from the cache if their content is discarded, although this automatic removal policy can be changed. If an NSDiscardableContent object is put into the cache, the cache calls discardContentIfPossible on it upon its removal.

Share:
62,224
Thizzer
Author by

Thizzer

Software developer at heart. Interested in all things Tech.

Updated on March 20, 2020

Comments

  • Thizzer
    Thizzer about 4 years

    Can someone give an example on how to use NSCache to cache a string? Or anyone has a link to a good explanation? I can't seem to find any..

  • Thizzer
    Thizzer about 13 years
    how to instantiate the NSCache object? I seem to loose all cached info every time I run the app. I use; [[NSCache alloc] init]
  • Jonathan Grynspan
    Jonathan Grynspan about 13 years
    It's not a permanent cache on disk. It's in memory only, so yes, it gets destroyed each time your app stops running.
  • barfoon
    barfoon over 12 years
    Is this cache maintained when after the application enters the backgruond? (i.e after applicationDidEnterBackground)
  • Jonathan Grynspan
    Jonathan Grynspan over 12 years
    If the application is not terminated and the NSCache object is not deallocated, then yes, it will remain in memory. Its contents may still be subject to culling however.
  • Michael
    Michael over 12 years
    Shouldn't the example be: NSAssert(myCache == nil, @"cache object is missing"); and not != nil?
  • Jonathan Grynspan
    Jonathan Grynspan over 12 years
    No. An assertion asserts that something is true, i.e. that the statement within is expected to be true. We are asserting that the object assignment and/or creation was successful.
  • Robert
    Robert almost 12 years
    @JonathanGrynspan, Im having trouble using NSCache. it dosn't seam to auto evict when there is a memory warning. Am I doing something wrong? stackoverflow.com/questions/11520815/…
  • Jonathan Grynspan
    Jonathan Grynspan almost 12 years
    It isn't required to. The times at which NSCache will evict values are an implementation detail. If you're finding you're getting a lot of memory warnings, you may want to empty the cache manually at that point (-removeAllObjects.)
  • Gabriel.Massana
    Gabriel.Massana about 11 years
    Yes. Save: [imagesDictionary setObject:imageData forKey:@"KEY"]; retrieve: NSData *imageData = [imagesCache objectForKey:@"KEY"];
  • kas-kad
    kas-kad about 11 years
    save data to chache: [imagesCache setObject:imageData forKey:@"KEY"];
  • Gabriel.Massana
    Gabriel.Massana about 11 years
    I just edited the post changed: imagesDictionary for imagesCache. Thx
  • Jasper
    Jasper almost 9 years
    An equivalent swift example?
  • Thizzer
    Thizzer almost 9 years
    You can implement the NSDiscardableContent protocol but this is not required. As it seems NSDiscardableContent is always removed from NSCache when there are no more references. Objects other than NSDiscardableContent object are stored in NSCache until there is 'memory is tight' and NSCache is going to be cleared.
  • Andrew
    Andrew almost 8 years
    do you know how to implement this in swift 3?
  • AmitaiB
    AmitaiB over 7 years
    This should work: class Cache: NSCache<AnyObject, AnyObject> { static let shared = NSCache<AnyObject, AnyObject>() private override init() { super.init() } }
  • user3552519
    user3552519 almost 7 years
    In case when the objects are difficult to recreate, should we go with "NSMutableDictionary" or something else ?