title: Performance for retrieving PHAssets with moments
body: <p>I am currently building a gallery of user photos into an app. So far I simply listed all the user's photos in a <code>UICollectionView</code>. Now I would like to add moment clusters as sections, similar to the iOS Photos app.</p>
  
  <p>What I am doing (a bit simplified):</p>
  
  <pre><code>let momentClusters = PHCollectionList.fetchMomentLists(with: .momentListCluster, options: options)
  momentClusters.enumerateObjects { (momentCluster, _, _) in
      let moments = PHAssetCollection.fetchMoments(inMomentList: momentCluster, options: nil)
      var assetFetchResults: [PHFetchResult&lt;PHAsset&gt;] = []
      moments.enumerateObjects { (moment, _, _) in
          let fetchResult = PHAsset.fetchAssets(in: moment, options: options)
          assetFetchResults.append(fetchResult)
      }
      //save assetFetchResults somewhere and use it in UICollectionView methods
  }
  </code></pre>
  
  <p>Turns out this is A LOT more time-intensive than what I did before - up to a minute compared to about 2 seconds on my iPhone X (with a gallery of about 15k pictures). Obviously, this is unacceptable.</p>
  
  <p>Why is the performance of fetching moments so bad, and how can I improve it? Am I using the API wrong?</p>
  
  <p>I tried loading assets on-demand, but it's very difficult, since I then have to work with estimated item counts per moment, and reload sections while the user is scrolling - I couldn't get this to work in a way that is satisfactory (smooth scrolling, no noticable reload).</p>
  
  <p>Any help? How is this API supposed to work? Am I using it wrong.</p>
  
  <h1>Update / Part solution</h1>
  
  <p>So after playing around, it turns out that the following was a big part of the problem:
  I was fetching assets using options with a sort descriptor:</p>
  
  <pre><code>let options = PHFetchOptions()
  options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
  options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
  let assets = PHAsset.fetchAssets(in: moment, options: options)
  </code></pre>
  
  <p>It seems sorting doesn't allow PhotoKit to make use of indices or caches it has internally. Removing the <code>sortDescriptors</code> speeds up the fetch significantly. It's still slower than before and any further tips are appreciated, but this makes loading times way more bearable.</p>
  
  <p>Note that, without the sort descriptor, assets will be returned oldest ones first, but this can be easily fixed manually by retrieving assets in reversed order in <code>cellForItemAt:</code> (so the cell at <code>0,0</code> will get the <em>last</em> asset of the first moment)</p>