Body, Identity, and Lifetime in SwiftUI

jbakerlent1 pts0 comments

Body, Identity, and Lifetime in SwiftUI - by John

jbakerlent

SubscribeSign in

Body, Identity, and Lifetime in SwiftUI<br>An exploration of SwiftUI view updates

John<br>Jun 03, 2026

Share

In SwiftUI, the phrase “the view updated” is overloaded. View updates can involve many things — body recomputation, structural identity comparison, state lookup, and more.<br>We know that SwiftUI views are ephemeral value types that can be reconstructed frequently, but just because the body property is reevaluated does not mean that an entire new view with a different identity and new state is created. These two events are easily conflated since they may both involve the same SwiftUI code being executed again, but they have very different consequences. So let’s first understand how to distinguish simple changes to a view’s description from changes to its identity.<br>Thanks for reading jbakerlent! Subscribe for free to receive new posts and support my work.

Subscribe

One caveat that I feel obligated to add is that SwiftUI's reconciliation rules aren't documented and have shifted across releases. So the description below reflects the current model, but not necessarily a contractual guarantee.<br>View Descriptions

A description change is a new answer to “what should this view look like now?” A description-level change occurs when SwiftUI reevaluates a view’s body and produces a new description of the interface. The view still occupies the same structural position in the view tree, but some aspect of its rendered output has changed.<br>struct CounterView: View {<br>@State private var count = 0

var body: some View {<br>VStack {<br>Text("Count: \(count)")

Button("Increment") {<br>count += 1

In the above snippet, changes to count cause body to be recomputed, producing a new description of the interface. But SwiftUI can still reconcile that description against the same structural identity, so the state associated with the counter remains intact.<br>View Identity

An identity change is a new answer to “is this still the same conceptual view?” Identity is closely tied to structure. When the shape of the produced view tree changes — a conditional branch is taken, an element appears or disappears, a view moves between containers — SwiftUI must determine how elements in the new tree correspond to elements in the previous tree. Not every change qualifies — changing a modifier value usually leaves identity intact, for instance — but when correspondence genuinely breaks, new identities and new lifetimes are established.<br>if isHighlighted {<br>Text(title)<br>.font(.headline)<br>} else {<br>Text(title)<br>.font(.body)

Here, the change is no longer purely descriptive. Each branch of the conditional has its own identity. When isHighlighted flips, SwiftUI tears down the Text from the true branch and creates the Text from the false branch — these are two distinct identities, not one view receiving a new description. That said, toggling back and forth doesn’t spawn endless new identities; it will alternate between two stable ones, each with its own lifetime.<br>This example is particularly surprising because both branches are just Text(title) with a different font, so it’s tempting to expect SwiftUI to recognize them as the same view and simply update the font. It doesn’t. The if/else is a structural fork, and structure determines identity. Because Text holds no state, the identity change here costs you nothing observable — but the font change won’t animate across the branch boundary, and if either branch held a stateful child view, that state would be discarded on every toggle. (You can collapse this into a single identity by changing it to Text(title).font(isHighlighted ? .headline : .body).)<br>For a deeper look at structural identity and how it is represented, see this article.<br>State Storage

One of the reasons the distinction between identity and description matters is that ordinary let and var properties are stored directly on the View struct and are therefore recreated with the view value. @State is different. Although a @State property is declared inside the view, its storage is managed externally by SwiftUI and tied to the view’s identity in the view tree.<br>As a result, if some upstream event causes CounterView (in the above example) to be recreated, count is not necessarily reinitialized. As long as SwiftUI can reconcile the new description against the same identity, the existing state storage can be looked up and reused.<br>Performance Implications

This is why recomputing body is usually less consequential. SwiftUI is designed to repeatedly ask views for new descriptions of the interface. As long as those descriptions can be reconciled with the same identity, the lifetime associated with that identity continues, and SwiftUI can preserve the state attached to it.<br>Identity changes are more significant. When a view moves to a different position, is replaced by a different branch, or otherwise no longer corresponds to the same place in the view tree, SwiftUI may establish a new...

view identity swiftui body state description

Related Articles