How to improve performance of UCollectionView containing lots of small images? How to improve performance of UCollectionView containing lots of small images? ios ios

How to improve performance of UCollectionView containing lots of small images?


I can propose alternative way that probably can solve your problem:
Consider to render blocks of images to single composed images. Such large image should cover size of app window. For user it will be looked like collection of small images, but technically it will be table of large images.

Your's current layout:

 |      |      |      | | cell | cell | cell |  -> cells outside of screen |      |      |      |*************************|      |      |      |**| cell | cell | cell |* -> cells displayed on screen*|      |      |      |**----------------------**|      |      |      |* *| cell | cell | cell |* -> cells displayed on screen*|      |      |      |**----------------------**|      |      |      |**| cell | cell | cell |* -> cells displayed on screen*|      |      |      |************************* |      |      |      | | cell | cell | cell |  -> cells outside of screen |      |      |      |

Proposed layout:

 |                    | |     cell with      | |   composed image   |  -> cell outside of screen |                    |*************************|                    |**|                    |**|                    |* *|                    |* *|     cell with      |**|   composed image   |* -> cell displayed on screen*|                    |**|                    |**|                    |* *|                    |* *|                    |************************* |                    | |     cell with      | |   composed image   |  -> cell outside of screen |                    |

Ideally if you pre-render such composed images and put them to project at build time, but you can also render them in runtime. For sure first variant will work much more faster. But in any case single large image costs less memory then separate pieces of that image.

If you have possibility to pre-render them then use JPEG format. In this case probably your first solution (load images with [UIImage imageNamed:] on main thread) will work good because less memory used, layout is much more simpler.

If you have to render them in runtime then you will need use your current solution (do work in background), and you will still see that image misplacements when quick animation happens, but in this case it will be single misplacement (one image covers window frame), so it should look better.

If you need to know what image (original small image 35x35) user clicked, you can use UITapGestureRecognizerattached to cell. When gesture is recognized you can use locationInView: method to calculate correct index of small image.

I can't say that it 100% resolves your issue, but it makes sense to try.


  1. There is no need to fetch image from document directory every time the cell appears.
  2. Once you fetch the image you can save same in NSCache, next time you just have to get image from NSCache instead of fetching it again from document directory.
  3. Create an object for NSCache objCache;
  4. In your cellForItemAtIndexPath, just write down

    UIImage *cachedImage = [objCache objectForKey:arr_PathFromDocumentDirectory[indexPath.row]];if (cachedImage) {    imgView_Cell.image = cachedImage;} else {    dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);    dispatch_async(q, ^{        /* Fetch the image from the Document directory... */        [self downloadImageWithURL:arr_PathFromDocument[indexPath.row] completionBlock:^(BOOL succeeded, CGImageRef data, NSString* path) {            if (succeeded) {                dispatch_async(dispatch_get_main_queue(), ^{                    UIImage *img =[UIImage imageWithCGImage:data];                    imgView_Cell.image = img;                    [objCache setObject:img forKey::arr_PathFromDocument[indexPath.row]];                });            }        }];    });}
  5. Once you fetch the image, set it in NSCache with path. Next time it is going to check if already downloaded then set from cache only.

If you need any assistance, please let me know.

Thanks!


Change from PNG to JPEG will not help saving the memory, because when you load an image from file to memory, it's extracted from the compressed data to uncompressed bytes.

And for the performance issue, I would recommend that you load the image asynchronously and update the view by using delegate/block. And keep some images in memory(but not all of them, let's say 100)

Hope this helps!