title: How to improve performance of UCollectionView containing lots of small images?
body: <p>In my iOS app I have <code>UICollectionView</code> that displays around 1200 small (35x35 points) images. The images are stored in application bundle.</p>
  
  <p>I am correctly reusing <code>UICollectionViewCell</code>s but still have performance problems that vary depending on how I address image loading:</p>
  
  <ul>
  <li><p>My app is application extension and those have limited memory (40 MB in this case). Putting all 1200 images to Assets catalog and loading them using <code>UIImage(named: "imageName")</code> resulted in memory crashes - system cached images which filled up the memory. At some point the app needs to allocate bigger portions of memory but these were not available because of cached images. Instead of triggering memory warning and cleaning the cache, operating system just killed the app.</p></li>
  <li><p>I changed the approach to avoid images caching. I put images to my project (not to asssets catalog) as png files and I am loading them using <code>NSBundle.mainBundle().pathForResource("imageName", ofType: "png")</code> now. The app no longer crashes due to memory error but loading of single image takes much longer and fast scrolling is lagging even on the newest iPhones. </p></li>
  </ul>
  
  <p>I have full controll over the images and can transform them for example to .jpeg or optimize them (I already tried <a href="https://imageoptim.com" rel="nofollow noreferrer">ImageOptim</a> and some other options without success).</p>
  
  <p>How can I resolve both these performance problems at once? </p>
  
  <hr>
  
  <p><strong>EDIT 1:</strong></p>
  
  <p>I also tried loading images in background thread. This is code from my subclass of <code>UICollectionViewCell</code>:</p>
  
  <pre><code>private func loadImageNamed(name: String) {
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { [weak self] () in
          let image = bundle.pathForResource(name, ofType: "png")?.CGImage
          if name == self?.displayedImageName {
              dispatch_async(dispatch_get_main_queue(), {
                  if name == self?.displayedImageName {
                      self?.contentView.layer.contents = image
                  }
              })
          }
      })
  }
  </code></pre>
  
  <p>This makes scrolling smooth without consuming additional memory for caching <strong>but</strong> when scrolling to some location programatically (for example when <code>UICollectionView</code> scrolls to top) <strong>it causes another problem</strong>: During scrolling animation the images do not update (scroll is too fast for them to load) and after scrolling is finished it takes wrong images are displayed for fraction of second - and one after another replaced with correct ones. This is very disturbing visually.</p>
  
  <hr>
  
  <p><strong>EDIT 2:</strong></p>
  
  <p>I cannot group small images into bigger composed images and display those as suggested by <a href="https://stackoverflow.com/a/31869978/311865">this answer</a>.</p>
  
  <p>Reasons: </p>
  
  <ul>
  <li>Consider different screen sizes and orientations. There would have to be precomposed images for each of them which would make the app download huge. </li>
  <li>The small images can by displayed in different order, some of them might be hidden in some situation. I surrely cannot have precomposed images for each possible combinations and orders.</li>
  </ul>