Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCache auto-removal policy

What are some of the NSCache's auto-removal policies? Apple's documentation does not mention them, and I experimentally discovered that NSCache does not respond to memory warning.

like image 789
Evil Nodoer Avatar asked Jun 02 '12 00:06

Evil Nodoer


People also ask

Is NSCache thread safe?

One more thing about NSCache is, it is thread safe. We can access it from any thread without worrying about managing threads while accessing NSCache. You can set & get name for cache. The default value is an empty string (“”).

Is NSCache persistent?

NSCache is really nice for a few reasons: It stores data in memory only. If our app gets killed, this memory is freed up and it's not persisted to disk. The key-value pair mechanism lets us very easily set and get cached content.


2 Answers

NSCache does not respond to UIApplicationDidReceiveMemoryWarningNotification, but it does automatically evict its objects in low memory situations, obviously using some other mechanism.

While I previously suggested observing UIApplicationDidReceiveMemoryWarningNotification, this is not the case. No special handling for low memory situations is needed, as NSCache handles this automatically.


Update:

As of iOS 7, the NSCache not only doesn't respond to memory warnings, but it also does not appear to properly purge itself upon memory pressure, either (see NSCache crashing when memory limit is reached (only on iOS 7)).

I subclass NSCache to observe UIApplicationDidReceiveMemoryWarningNotification, and purge the cache upon memory warning:

@interface AutoPurgeCache : NSCache
@end

@implementation AutoPurgeCache

- (id)init
{
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeAllObjects) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

    // if not ARC, also
    //
    // [super dealloc];
}

@end
like image 78
Rob Avatar answered Sep 30 '22 08:09

Rob


You're best off treating NSCache as a black box, as much as you can.

From Caching and Purgeable Memory (emphasis mine):

When adding items to a cache, you can specify a cost value to be associated with each key-value pair. Call the setTotalCostLimit: method to set the maximum value for the sum of all the cached objects’ costs. Thus, when an object is added that pushes the totalCost above the totalCostLimit, the cache could automatically evict some of its objects in order to get back below the threshold. This eviction process is not guaranteed, so trying to manipulate the cost values to achieve specific behavior could be detrimental to the performance of the cache. Pass in 0 for the cost if you have nothing useful, or use the setObject:forKey: method, which does not require a cost to be passed in.

Note: The count limit and the total-cost limit are not strictly enforced. That is, when the cache goes over one of its limits, some of its objects might get evicted immediately, later, or never, all depending on the implementation details of the cache.

like image 44
Shaggy Frog Avatar answered Sep 30 '22 08:09

Shaggy Frog