What are blending and overdraw, how do opaque views help, and what are dirty rectangles?
Predict first
A cell’s label sits on a solid white cell but has a clear background. What do you change to cut blending?
// A: give the label the same opaque background colour and set isOpaque
// B: raise its alpha
// C: add a shadow
- A
- B
- C
Mental model. Painting over a solid wall is one coat. Painting on glass with several panes behind it means mixing colours at every step, for every pane.
When a layer is opaque (isOpaque true, its colour fully opaque, and its contents without alpha), the GPU can write its pixels directly. When it is translucent, the GPU must blend: read the pixels behind, combine them using the alpha, and write the result, for every pixel and every layer stacked there. Stacks of translucent layers (a label with a clear background over an image over a gradient) multiply that work, which is called overdraw, and filling large areas many times is exactly what limits GPU fill rate on a full-screen scrolling view. The fix is to give views an opaque background colour where possible (set backgroundColor and isOpaque = true, particularly for table or collection cells and labels over a known colour), use images without an alpha channel when they do not need one, and avoid layering when one view would do. The simulator’s Color Blended Layers option shows blended regions in red.
The other half is the CPU: draw(_:) is given a dirty rectangle. If you call setNeedsDisplay() the whole view is redrawn; setNeedsDisplay(_ rect:) redraws only the affected area, and your draw(_:) should respect rect and skip work outside it. Combine that with caching static parts. Drawing is also bounded by pixel count: a view at 3× scale is nine times the pixels of the same view at 1×. Finally, opacity is not free: a view with alpha below 1 and subviews may need group opacity (an offscreen flatten). Prefer setting the alpha on the individual leaf views or use a colour with alpha, when the result looks the same.
A known, opaque background lets the GPU write the label’s pixels directly instead of blending them with whatever is behind.
Common traps
- Leaving a cell’s labels with a clear background over a coloured cell. Each label is a blended layer; give it the background colour and mark it opaque.
- Redrawing the whole view for a tiny change. Pass a dirty rect to
setNeedsDisplayand respect it indraw.
They might follow up with
- How do you see blending? The simulator’s Color Blended Layers option, and the Core Animation instrument.
- Why does a high-resolution screen make drawing costlier? The pixel count rises with the square of the scale factor.
Related questions
- 9.3.1 What is offscreen rendering, which properties cause it, and how do you avoid the cost?
- 9.5.1 How do you draw with Core Graphics and UIBezierPath, and how do scale and caching affect it?
- 9.1.2 What is the difference between layoutSubviews and draw(_:), and what triggers each?
← What is offscreen rendering, which properties cause it, and how do…