Skip to content

Structural Identity (SwiftUI)

A SwiftUI guide for coding agents. Also covers view identity if else, conditionalcontent, state lost on condition change, unwanted animation branch, inert view modifiers.

Structural identity is how SwiftUI recognizes a view by its position in the layout description, without an explicit ID. Branching with if gives the two branches different identities, so SwiftUI destroys and recreates views when the condition flips. Keeping identity stable preserves state and avoids surprise animations.

Branches Create New Identities

An if let in a body compiles to _ConditionalContent, one identity per branch. When the condition changes, SwiftUI tears one view down and builds the other, deallocating the old view's state and animating the swap.

struct UserView: View {
  let user: User?

  var body: some View {
    if let user = user {
      LoggedUser(user: user)
    } else {
      AnonymousUserView()
    }
  }
}

print(Mirror(reflecting: UserView(user: nil).body))
// Mirror for _ConditionalContent<LoggedUser, AnonymousUserView>

That is fine when the branches are genuinely different views. It is a bug factory when both branches hold the same view:

// Loses ComplexView's state on every toggle, and animates the swap.
if isEnabled {
  ComplexView()
} else {
  ComplexView()
    .disabled(true)
}

Inline the Condition into the Modifier

Move the condition inside the modifier value and the branch disappears. SwiftUI sees one view whose modifier value changed, so state survives and nothing is recreated.

struct AchievementView: View {
  let isEnabled: Bool

  var body: some View {
    ComplexView()
      .disabled(isEnabled ? false : true)
  }
}

The rule: branch with if or switch only to present genuinely different views. Otherwise keep one view and vary its modifiers.

Inert Modifiers Are Free

Some modifiers cost nothing at their neutral value: padding(0) and opacity(1) change nothing in the view tree, and SwiftUI skips them. That makes them safe to apply unconditionally with a ternary.

ComplexView()
  .opacity(isEnabled ? 1 : 0)
  .padding(isEnabled ? 8 : 0)

This is the performant way to show, hide, and adjust a view without touching its identity.

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-structural-identity" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems