How do prefetching and self-sizing cells keep scrolling smooth, and what can still make it janky?

7.5.4 · L5 · Interview

Predict first

Is prefetching enabled by default?

import UIKit

let cv = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
print(cv.isPrefetchingEnabled)
  • true
  • false

Mental model. A kitchen that starts the next dishes while you eat the current one. It is a gain only if the dishes are cheap to prepare and can be thrown away when you leave.

Prefetching is on by default (isPrefetchingEnabled is true): the collection view asks for cells slightly before they are needed, spreading creation cost across frames. For data, adopt UICollectionViewDataSourcePrefetching: prefetchItemsAt tells you which index paths are coming, so you can start image or network loads, and cancelPrefetchingForItemsAt tells you which were abandoned, so you can cancel. It is a hint, not a guarantee, and prefetched work must be cancellable and cheap to discard.

Self-sizing means a cell reports its own height from its Auto Layout constraints or its content configuration, which suits variable text. With compositional layout you give the item an .estimated dimension and the system measures the real size after configuring the cell. Estimates that are far from the truth cause scroll-bar jumps and extra layout passes. Typical jank: heavy work in the cell provider (decoding images, formatting dates), constraints that cause a wide layout pass, offscreen-rendered effects such as shadows plus rounded corners without a shadow path, and reloading the whole collection instead of applying a diff. Find it with the Time Profiler and the Hangs and Animation Hitches instruments rather than by guessing.

Cell prefetching is on by default; data prefetching additionally needs you to set a prefetchDataSource.

Common traps

  • Starting non-cancellable work in prefetchItemsAt. Rows that scroll away still cost you.
  • Using a wildly wrong estimated size. The system must re-measure and the scroll indicator jumps.

They might follow up with

  • Where do you cache decoded images? In a memory cache keyed by item and size, filled by the prefetch step, not inside the cell.
  • How do you see hitches? Instruments’ Animation Hitches, and MetricKit for field data.

Related questions

  • 7.5.3 How does cell reuse work, and what are the classic reuse bugs?
  • 7.5.1 How does compositional layout describe a collection view, and how do you read its output?
  • 6.3.1 What is a run loop, and what happens in one iteration?

← How does cell reuse work, and what are the classic reuse bugs?