Slide 1

Slide 1 text

High-Performant UICollectionViewLayout

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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)

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Thank you Michael Ochs @_mochs https://pspdfkit.com/blog/