3

I came across a problem that only happened on iOS 8. I used the NSCache to store my images. After receiving memory warning, I would fetch images and store into cache again. However the cache can't store my images anymore after warning. It always returns nil to me by using objectForKey:.
Here's part of my code:

 @interface ViewController ()
{
    NSCache *imageCache;
}

@implementation ViewController
- (instancetype)init
{
    self = [super init];
    if (self) {
        imageCache = [[NSCache alloc] init];
        [imageCache setTotalCostLimit:1024 * 1024 * 1];
    }
    return self;
}
- (void)imageDownloadManager:(ImageDownloadManager *)manager didReceiveImage:(UIImage *)image forObjectID:(NSString *)objecID
{   
    NSUInteger cost = [UIImageJPEGRepresentation(image, 0) length];
    image = [image smallImageWithCGSize:kImageThumbSize];
    [self.imageCache setObject:image forKey:objectID cost:cost];
    NSLog("image: %@",[self.imageCache objectForKey:objectID]);  //return nil
}
@end

Thanks :)

SOLUTIONS

You have to set countLimit and the value must greater than 0. Then you could use totalCostLimit as well.

yuhua
  • 1,239
  • 8
  • 18
  • “Yet, when memory is low, it will automatically discard some of its elements in order to free up memory for other application”… from here https://developer.apple.com/library/ios/documentation/Performance/Conceptual/ManagingMemory/Articles/CachingandPurgeableMemory.html – TonyMkenu Dec 04 '14 at 09:09
  • yeah! but it could init after memory warning and supposed to be able to store/retrieve. It seems that it can't `setObject:` again after warning, and i'm sure `imageCache` is NOT nil as well. – yuhua Dec 04 '14 at 09:15

1 Answers1

1

I experienced the same problem (and only under iOS 8.1) and got it working by assigning a countLimit instead of a totalCostLimit.

// getter
- (NSCache *)cache
{
   if (!_cache) {
      _cache = [[NSCache alloc] init];
      _cache.countLimit = aLimit;
   }
   return _cache;
}
boll
  • 57
  • 3