A timer that re-renders the whole screen

SwiftUI Senior Swift 5.5+ iOS 15+ Reviewed By Alok Singh

Pick the fix

A clock label updates every second, and a heavy chart on the same screen re-renders each tick. Best fix?

Options
Hint 1 of 1

Which view actually needs the time?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Move the clock into a small ClockView using TimelineView(.periodic(from: .now, by: 1))

Correct. Only the clock depends on time now.

Why not the others?
  • B Add .drawingGroup() to the chart. That speeds up drawing; the chart's body still runs every second.
  • C Tick every 5 seconds instead. It hides the cost and makes the clock wrong.
  • D Wrap the screen in AnyView. Type erasure makes diffing worse, not better.

30-second answer

Find what the timer invalidates. Usually the ticking state lives high up, so every tick re-runs a big body. Move the time display into its own small view (or a TimelineView), so only that view depends on the clock. Confirm with Self._printChanges() and the SwiftUI instrument before and after.

Practise saying it · 45 s. No recording, just a timer

Explain how you'd fix constant re-renders.

Say your answer out loud, then check which of these points you covered:

  • Measure with _printChanges / Instruments
  • Move state to the smallest view
  • TimelineView for clocks

Deep dive

TimelineView(.periodic(from: .now, by: 1)) redraws only its content.

Observation tracks per property, so keep ticking values out of models read by heavy views.

Heavy subviews such as charts should depend only on their own data.

drawingGroup helps rendering cost, not re-evaluation.

Common mistakes

  • Lowering the timer rate to hide the problem.
  • Wrapping everything in EquatableView before measuring.
  • Putting a Timer publisher in a view model that the whole screen reads.

Senior take & follow-ups

Seniors measure first, move state to the smallest view that needs it, then measure again.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you prove the fix worked?

    Show hint

    Count body calls with _printChanges, or use the SwiftUI instrument.

  2. Where would you store an elapsed time?

    Show hint

    Store a start date and compute the elapsed time in the small view.

Suggest a fix if something here is wrong or out of date.