Consider an app that uses UICollectionViewDiffableDataSource for the data source of UICollectionView.
private func makeDataSource() -> DataSource {
return DataSource(collectionView: collectionView) { collectionView, indexPath, task in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TaskCell", for: indexPath) as? TaskCell
cell?.title = task.title
return cell
}
}
Collection has only one section:
enum Section {
case main
}
and loads 10 000 items represented by Task:
import Foundation
struct Task {
let id: String
let title: String
}
extension Task: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
ViewController that holds the collection, implements sizeForItemAt and calculate size based on e.g. title length:
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
let task = dataSource.snapshot().itemIdentifiers(inSection: .main)[indexPath.item]
let height = calculateHeight(for: task)
return CGSize(width: collectionView.frame.width, height: heigh)
}
Now it works fine, except that .itemIdentifiers(inSection: .main) works extremely slow as for its complexity. Every call of this function takes few milliseconds which multiplied by 10 000 results in blocking UI for few seconds.
Why .itemIdentifiers(inSection:) is so slow? How else can I access item identifier when I want to calculate cell size making sure that it is synchronized with snapshot?