The SwiftUI Render Loop
We will first look into a number of examples of such cases where it is useful to know how the SwiftUI render loop works. Then we will explore the render loop in more detail and ask questions such as: when exactly is the body of a SwiftUI view evaluated. Not “when” as in under what circumstances, but as in: at which point in time? Is a view always drawn on screen immediately after a body is evaluated? How related are body evaluation and screen rendering even? We sometimes use the word “render” for evaluating a body of a view, does that even make sense?
[…]
When it is not doing anything, a SwiftUI app will have an idle
CFRunLoop
. It will wait for events from an input source such as touches, network events, timers or a display refresh. In response to a touch, SwiftUI may call a Button's action handler. If we put a breakpoint inside that action handler, we will see__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__
somewhere in the stack trace. This is because touch events are delivered from a type 0 input source.In response to an action that we perform in response to an event from in input source, we might update some
@State
variable in a view or call a function on an@ObservedObject
that in turns causes itsobjectWillChange
publisher to fire. In this case, the SwiftUI view is invalidated. This means that its body needs to be re-evaluated, but it would be inefficient to do that immediately. Maybe the same function that changed a@State
variable will change another@State
variable. Therefore, the body evaluation is scheduled to be executed later.