问题
NSCache is a rarely used tool which actually looks quite useful. I created a simple experiment to see how it works and it looks like it does not auto-evict data in low memory situations (or I am doing something wrong!)
- (void)viewDidLoad
{
_testCache = [[NSCache alloc] init];
// Allocate 600 MB of zeros and save to NSCache
NSMutableData* largeData = [[NSMutableData alloc] init];
[largeData setLength:1024 * 1024 * 600];
[_testCache setObject:largeData forKey:@"original_Data"];
}
- (IBAction)buttonWasTapped:(id)sender {
// Allocate & save to cache 300 MB each time the button is pressed
NSMutableData* largeData = [[NSMutableData alloc] init];
[largeData setLength:1024 * 1024 * 300];
static int count = 2;
NSString* key = [NSString stringWithFormat:@"test_data_%d", count++];
[_testCache setObject:largeData forKey:key];
NSMutableData* dataRecoveredFromCache = [_testCache objectForKey:@"original_Data"];
if (dataRecoveredFromCache) {
NSLog(@"Original data is ok");
} else {
NSLog(@"Original data is missing (purged from cache)");
}
}
So I ran the app in the simulator, and taped the button a few times however no items were evicted... The app eventually crashed:
2012-07-17 14:19:36.877 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:37.365 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:37.861 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:38.341 NSCacheTest[15302:f803] Data is ok
2012-07-17 14:19:38.821 NSCacheTest[15302:f803] Data is ok
NSCacheTest(15302,0xac0942c0) malloc: *** mmap(size=393216000) failed (error code=12)
*** error: can't allocate region
回答1:
From the doc (Emphasis mine): The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.
Apple does not state that the memory will be freed on memory warning - in my experience, the cache is most often purged when the app goes to background or when you add more large elements.
回答2:
Here's quoted docs ...
The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.
... as you can see it states that it removes some items, not all items. It depends on NSCache
internal policies, available memory, device status, etc. You shouldn't worry about these policies.
You can control them with countLimit
, totalCostLimit
properties and you can add object with cost, look at setObject:forKey:cost:
.
Also you can evict objects by yourself. Add NSDiscardableContent
protocol implementation to your objects and setEvictsObjectsWithDiscardedContent
: to YES
.
回答3:
I am using that class too. Note that the documentation states the NSCache is tied into the OS and probably has access to memory information deep within the OS. The memory warning is just that - it just sends a memory warning to the appDelegate/viewControllers.
If you really want to test your code out, you will probably need a test mode where you start mallocing lots of memory (creating a huge leak so to speak). You might need parcel this out in chunks during each main runloop, so the OS has the opportunity to see he memory going down (I have an app that chew ups lots of memory, and it does it so fast on the 3GS it just gets killed never having got a memory warning.
来源:https://stackoverflow.com/questions/11520815/nscache-is-not-evicting-data