Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCache removes all its data when app goes to background State

I am working with NSCache, I am using NSCache to store images. I am showing images on UITableView. Whenever I add images first they are resized and then added to the table and then to NSCache. eveything works fine.

But whenever app goes to background when I close the app and open again, My Cache will be empty and again my app resizes images and then show it, because of which at first I see a empty table.

I am not understanding why this is happening. Is this the intended behaviour of NSCache? .If yes then how can we improve the user experience so that use doesnt see the lag.

here is my code which was suggested to me by @ipmcc

Here category is my entity name (I am using coreData)

// A shared (i.e. global, but scoped to this function) cache
    static NSCache* imageCache = nil;
    // The following initializes the cache once, and only once
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        imageCache = [[NSCache alloc] init];
    });

    // Generate a cache key sufficient to uniquely identify the image we're looking for
    NSString* cacheKey = [NSString stringWithFormat: @"%@", category.name];
    // Try fetching any existing image for that key from the cache.
    UIImage* img = [imageCache objectForKey: cacheKey];
    self.imageView.image = img;

    // If we don't find a pre-existing one, create one
    if (!img)
    {
        // Your original code for creating a resized image...
        UIImage *image1 = [UIImage imageWithData:category.noteImage];

        CGSize newSize;
        if(image1.size.width == 1080 && image1.size.height == 400)
        {
            newSize = CGSizeMake(300, 111);
        }

        dispatch_async(dispatch_get_global_queue(0,0), ^{
            UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
            [image1 drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
            UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            dispatch_async(dispatch_get_main_queue(), ^{
                // Now add the newly-created image to the cache
                [imageCache setObject: newImage forKey: cacheKey];
                self.imageView.image = newImage;
            });
        });
    }
like image 437
Ranjit Avatar asked Dec 16 '13 08:12

Ranjit


1 Answers

Yes it does that, for some reason it instantly removes data from cache when app enters background even if there is no memory pressure. To fix this you have to tell NSCache that your data should not be discarded.

Here is how you fix this.

class ImageCache: NSObject , NSDiscardableContent {

    public var image: UIImage!

    func beginContentAccess() -> Bool {
        return true
    }

    func endContentAccess() {

    }

    func discardContentIfPossible() {

    }

    func isContentDiscarded() -> Bool {
        return false
    }
}

and then use this class in NSCache like this.

let cache = NSCache<NSString, ImageCache>()

and then set the data in cache like this

let cacheImage = ImageCache()
cacheImage.image = imageDownloaded
self.cache.setObject(cacheImage, forKey: "somekey" as NSString)

and to retrive the data

if let cachedVersion = cache.object(forKey: "somekey") {
     youImageView.image = cachedVersion.image
}
like image 147
Sharjeel Ahmad Avatar answered Sep 21 '22 12:09

Sharjeel Ahmad