Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 291
Shane Avatar asked Oct 19 '22 06:10

Shane


1 Answers

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

like image 146
Andrea Avatar answered Nov 15 '22 04:11

Andrea