Shane
Shane

Reputation: 397

swift - UICollectionView or UIImage - how to prevent image caching

I have a UICollectionView with 4 cells in a grid pattern and no scrolling. Each cell has a single imageView. The images are stored in the asset folder and retrieved by name reference (see below). After some UI action, the idea is to

collectionView.reloadData() 

and replace the image in each cell.

Everything works fine, but the memory use keeps climbing after each reload. I had assumed reloadData() dumps unnecessary data, but this experience has me puzzled. What's happening?

If it helps, I read somewhere loading an image with

UIImage(name: ...) 

caches the image. I've tried to confirm this but have drawn a blank.

My code is pretty straightforward so I'm wondering if this is some memory bug / feature for scrolling purposes (that I don't want).

Once again, I'm looking to stop the memory stockpiling. Any ideas?

Upvotes: 5

Views: 2257

Answers (3)

Andrea
Andrea

Reputation: 26383

I never had the chance to understand when the image cache is evicted.
Collection view cell are dequeued and reused. That means than right after a cell goes out of screen is put in a recycle bin, if the cell is need again is taken from that recycle bin and placed into you views hierarchy (this is called flyweight pattern I guess), basically you are saving the instantiation cost.
Thus when you deal with images and your images are not stored elsewhere in memory but just inside the image view, every time a cell is shown and an new image is passed to the image view the old image should be freed.
This could not happen if you store a reference to the old image elsewhere, for instance a cache or an array.
To load image from xcasset you can only use UIImage(name: ...) that means the image will be cached. Even if Apple says that this cache will be evicted in memory pressure situations and never seen this happening "in time" to avoid the app crashing.
What you can do is do not save in the xcasset folder, but anywhere in your project, in this way they will be loaded into your main bundle, you can load images from here by using the common:

let path = NSBundle.mainBundle().pathForResource(<#T##name: String?##String?#>, ofType: <#T##String?#>)
    let image = UIImage(contentsOfFile: path!)

Pay attention that path is an optional.
As a general rule, always try to save resources by using image of the same view size in pixel, the occupied space of an image means nothing, just how its compressed, when loaded in memory it takes n_pixel_height * n_pixel_width * n_channels bytes

Upvotes: 5

Proton
Proton

Reputation: 1365

In prepareForReuse method of your subclass UICollectionViewCell

func prepareForReuse()
{
    super.prepareForReuse();
    cell.imageView.image = nil;
}

Upvotes: -1

Amit Singh
Amit Singh

Reputation: 2698

You are doing it correctly, If you are using dequeueReusableCellWithReuseIdentifier(identifier:, forIndexPath:) method for cell reusability then it will surely handle the reusability of the cell.

You have no other way to load the images from the bundle.

Some slight changes in memory may reflect but its ok and go ahead

Upvotes: -1

Related Questions