Understanding structural identity in SwiftUI
Learn how SwiftUI optimizes UI updates.
10 Mar 2025 · 3 min read
Unlike traditional UI frameworks where we manually track and update UI elements, SwiftUI automatically refreshes views when state changes. However, redrawing everything would be inefficient. This is where structural identity comes in - it allows SwiftUI to determine which views actually need to be redrawn, optimizing performance.
Let's jump in and look at how this works.

What is structural identity?
When a state change occurs in SwiftUI, the framework reconstructs the entire view hierarchy. This might sound inefficient at first, but it's actually remarkably optimized, because SwiftUI views are lightweight value types (structs) and most importantly, because SwiftUI uses structural identity to avoid unneeded redrawings.
Structural identity is SwiftUI's way of recognizing whether a view before and after a state change is fundamentally the same view. When SwiftUI identifies views as structurally identical, it preserves their state and redraws only the parts that have changed.
A view's structural identity is determined by:
- Its type
- Its position in the view hierarchy
- The identity of its ancestors
Update vs. redraw in SwiftUI
While the terms update and redraw may sound interchangeably, they refer to different processes:
- Update: SwiftUI reinitializes the view evaluating the body property, while preserving state. This happens every time a state change occurs.
- Redraw: This is when SwiftUI sends rendering instructions to the GPU, updating the pixels on the screen. Just because a view is reinitialized doesn't mean it will be redrawn.
Structural identity in action
Consider this example:
struct ExampleView: View {@State private var isOn = truevar body: some View {VStack {Text("Is on: \(isOn ? "yes": "no")")Button("Switch") {isOn.toggle()}if (isOn) {BottomViewOn()} else {BottomViewOff()}}}}
When a user taps the "Switch" button:
- The isOn state variable changes.
- SwiftUI rebuilds the view hierarchy. That means ExampleView is reinitialized, and SwiftUI preserves the state isOn.
- Using structural identity, SwiftUI recognizes that Text and Button are fundamentally the same views as before.
- Since the Text view's content has changed, it gets redrawn.
- The Button view remains untouched because its content and structure haven't changed.
- What happens with BottomViewOn and BottomViewOff? When isOn changes, one view is removed from the hierarchy, and the other one is newly created. And any internal state within BottomViewOn or BottomViewOff is lost when switching between them.
How to persist state across both views?
If we want to keep state in BottomViewOn and BottomViewOff, we could:
- Extract their state to the parent view e.i. manage it externally or
- Use structural identity by making the following changes:
ZStack {BottomViewOn().opacity(isOn ? 1 : 0).accessibilityHidden(!isOn)BottomViewOff().opacity(isOn ? 0 : 1).accessibilityHidden(isOn)}
Instead using an if-else condition, we now keep both views in the hierarchy preserving structural identity.
Structural identity in lists
In SwiftUI, structural identity also plays an important role in lists. When using a List view, SwiftUI requires each item to have a unique identifier, either by conforming to Identifiable or by specifying an id key path. This allows SwiftUI to track individual items even when their order changes, preventing unnecessary redraws. Using unique IDs such as database IDs is a good practice because relying on indices or non-unique properties can lead to incorrect updates, glitches, or unexpected UI behavior when modifying the list dynamically.
SwiftUI as a black box
SwiftUI hides much of its inner workings, making it feel like a black box. SwiftUI decides what to update and redraw behind the scenes, so we can only experiment to understand its behavior. Many hope SwiftUI will be open-sourced someday, giving us a clearer look inside.



Newsletter
Like to support my work?
Say hi
Related tags
Articles with related topics
Latest articles and tips



