TechnologiesSwiftUI

SymbolEffectTransition struct

iOSmacOStvOSwatchOSvisionOSiOS 17.0+✓ renders

Creates a transition that applies the Appear, Disappear, DrawOn or

How it works

A SymbolEffectTransition describes how an SF Symbol animates as it is added to, removed from, or swapped within the view tree. Rather than letting a symbol pop in and out abruptly, you supply a transition that the system runs whenever the symbol's content or identity changes, producing the fluid, physically-grounded motion that's characteristic of SF Symbols. Reach for it when a symbol's value is data-driven — a state toggle, a status indicator, a mode switch — and you want the change between two glyphs to read as a single continuous animation. You don't usually construct one directly; you select a named transition such as the replace effect and hand it to a transition-aware modifier.

  1. Drive the symbol from state

    A symbol transition only fires when the symbol actually changes, so the glyph must be derived from a value that mutates. Here the Image(systemName:) resolves to either "wifi" or "wifi.slash" depending on isOn, and the Button flips isOn with isOn.toggle() — each toggle gives the transition a new symbol to animate to.

  2. Attach the transition with contentTransition(.symbolEffect)

    The transition is applied through the .contentTransition(.symbolEffect(...)) modifier, which tells SwiftUI to treat a change in the view's content as a symbol effect rather than a default cross-fade. This is the seam where SymbolEffectTransition plugs into the Image; without it, swapping the system name would simply replace one glyph with the next, no animation in between.

  3. Choose the effect: .replace

    The argument to .symbolEffect names which transition to run. The .replace effect animates the outgoing glyph away while bringing the incoming glyph in, so "wifi.slash" morphs into "wifi" as one motion. Other transition styles (such as scale-based appear/disappear effects) are selected the same way — by passing a different effect value in this position.

  4. Layer ordinary styling around it

    Because the transition operates on the symbol's content, it composes cleanly with the rest of the modifier chain. The .font(.system(size: 60)) sizing and the .foregroundStyle(isOn ? .blue : .gray) tint apply to whichever glyph is current, and the color change rides alongside the symbol replacement so both animate together when isOn flips.

Try it — Replace .contentTransition(.symbolEffect(.replace)) with .contentTransition(.symbolEffect(.replace.downUp)) and toggle the button to see the outgoing and incoming glyphs slide in opposite vertical directions instead of swapping in place.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

SymbolEffectTransition.swift
struct SymbolEffectTransitionDemo: View {
    @State private var isOn = false
    var body: some View {
        VStack(spacing: 24) {
            Image(systemName: isOn ? "wifi" : "wifi.slash")
                .font(.system(size: 60))
                .contentTransition(.symbolEffect(.replace))
                .foregroundStyle(isOn ? .blue : .gray)
            Button(isOn ? "Turn Off" : "Turn On") {
                isOn.toggle()
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}
Live preview
Turn On
Turn On
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →