Categories
Dev

UICollectionViewCell Auto Layout Performance

I’ve been converting the main posts view in Pinpoint from a table view to a collection view. Unfortunately, I found that it was stuttering even on my brand-new, ridiculously fast iPhone 6s Plus.

The cells have background images, buttons, and gradients, so I thought I’d need to optimize those. But when I spun up Instruments and had a look at the CPU usage I found that a lot of main thread CPU time was spent on layout.

Problem

When slowly scrolling through the collection view, I could see spikes like this when each row displayed. Something was taking too much time to prepare those collection view cells. Probably my collectionView:cellForItemAtIndexPath:, right?

Screenshot of instruments showing CPU spikes

Focusing in on one of those spikes, I could see that the cell re-use looked okay at only 4.1% of the CPU time. But what about that deep stack of Auto Layout calls? Something called -[UICollectionView _checkForPreferredAttributesInView:originalAttributes:] was taking up a lot of CPU time.

Instruments call tree

Solution

After a bit of searching, I stumbed across a blog post by Marcin Pędzimąż about UICollectionViewCell performance.

Marcin’s suggestion/solution was to use the following in your UICollectionViewCell subclass. Unfortunately he doesn’t say why.

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    return layoutAttributes;
 }

This completely solved my problem. Scrolling is now super smooth even on a 4S.

I still haven’t found any documentation on why the default implementation is so expensive, but someone else also found that this solved their problem.

I doubt this is a silver bullet for collection view performance, but worth a shot if you get stuck.