The Problem • We need to support large documents (10k+ pages) • UICollectionViewFlowLayout is slow for certain scenarios • Size calculations for each site is a slow task • UICollectionViewFlowLayout requires all sizes to be known up front* • No later than at render time
The Problem • A flow layout is complex • The position of item i can only be calculated when all positions up to i-1 are known • Once element i is calculated, previous elements might need to be changed • The size of the collection view can only be calculated when the position of item n is known 2 3 1 5 6 4 8 9 7 11 12 10 14 15 13 17 18 16
The Solution (iOS 8+) • Estimated cell sizing • All cells after the ones currently on screen are calculated with an estimate • This works because the collection view size is only needed to give the scroll indicator the right position and length • Caveats: • Once the delegate asks you still need to have the right size at hand • Often it makes sense to update estimates once you have calculated some sizes
The Solution (iOS 8+) • Estimated cell sizing • All cells after the ones currently on screen are calculated with an estimate • This works because the collection view size is only needed to give the scroll indicator the right position and length • Caveats: • Once the delegate asks you still need to have the right size at hand • Often it makes sense to update estimates once you have calculated some sizes 1 2 3 4 5 6
The Solution (iOS 10) • Automatic estimated cell sizing • Estimate is calculated based on the already known item sizes and constantly updated • Reduced amortize cost by cell prefetching
The Solution (iOS 10) • Automatic estimated cell sizing • Estimate is calculated based on the already known item sizes and constantly updated • Reduced amortize cost by cell prefetching • Caveat: • The correct size still needs to be known when the cell is configured by the collection view
Additional Features (iOS 10) • UICollectionViewFlowLayout now as automatic estimated cell sizing • It constantly reevaluates the estimated size based on the known cells • Often much more accurate than just providing a constant estimate • UICollectionView has UICollectionViewDataSourcePrefetching • Like cell prefetching but for the data source behind it • Collection view notifies you when to fetch data (in the background)
What they don’t tell you • UICollectionViewFlowLayout does have a hard time for 10k+ items, no matter how much you optimize • This problem gets worse the closer you come towards the end • It’s a linear problem (at least) • They tell you start your custom layouts based on UICollectionViewFlowLayout • Don’t! Use UICollectionViewLayout • There is a s$%t load of caching going on, and chances are pretty good that their cache is not in sync with what you cache
What they don’t tell you • When writing your own layout, cache everything • After that, cache the things you didn’t cache until now • It’s crucial to invalidate as little as possible in your caches • UICollectionViewLayoutInvalidationContext is great for that • But: You do not need to set every property there • Values like CGSizeZero do not mean 0, it really means I don’t know
What they don’t tell you • Don’t invalidate you cache right away, wait for prepareLayout • The cycle is as follows: • shouldInvalidateLayoutFor... • invalidationContextFor... • invalidateLayout • invalidateLayoutWithContext: • prepareLayout
What they don’t tell you • No matter what they tell you, creating a custom collection view layout that is performant is… • solving mathematical issues • not trivial • much harder than it looks