← Alle Beitrage

Symbol Effects: Das integrierte Animations­vokabular von SwiftUI für jedes Icon

SF Symbols 5 (iOS 17) lieferte ein Animationsvokabular, das jede iOS-App sprechen kann. SF Symbols 6 (iOS 18) hat es erweitert. SF Symbols 7 (iOS 26) erweitert es erneut. Die meisten Apps stellen ihre Icons noch immer als statische Bilder dar. Das Animationsvokabular liegt in SF Symbols.app und hinter einem einzigen SwiftUI-Modifier bereit, kostet bei der Übernahme nichts, ist vom Animations-Team von Apple so gestaltet, dass es sich nativ anfühlt, und respektiert Barrierefreiheits-Einstellungen ohne projektspezifische Arbeit. Diese Auslassung ist eines der häufigsten Qualitätsverlustmuster in aktuell ausgelieferten iOS-Apps.

Das Vokabular benennt eine Reihe von Dingen, die ein Icon tun kann: Es kann hüpfen, pulsieren, skalieren, sich durch ein anderes Symbol ersetzen, Farbe über seine Ebenen hinweg animieren, atmen, rotieren, wackeln, erscheinen oder verschwinden. Jedes Verb hat eine spezifische Bedeutung, einen spezifischen audiovisuellen Charakter und einen spezifischen Moment im Verhalten der App, in dem es seinen Platz verdient. Das System gibt der Entwicklerin oder dem Entwickler die Verben; die Aufgabe besteht darin auszuwählen, welches zu welchem Moment passt.

TL;DR

  • Der SwiftUI-Modifier .symbolEffect(...) animiert jedes SF Symbol mit Effekten wie .bounce, .pulse, .scale, .variableColor, .breathe, .rotate, .wiggle, .appear und .disappear1.
  • Eine separate API-Oberfläche, .contentTransition(.symbolEffect(.replace)), führt einen gestalteten Übergang zwischen zwei unterschiedlichen SF Symbols aus. Der replace-Effekt liegt auf ContentTransition, nicht auf SymbolEffect; beide arbeiten zusammen, sind aber unterschiedliche APIs.
  • Effekte können einmal laufen (wertgesteuert über value:), gehalten werden, solange ein Status wahr ist (zustandsgesteuert über isActive:), oder kontinuierlich wiederholt werden (options: .repeating).
  • Die Performance ist im Wesentlichen kostenlos: Die Animationen werden über das SF-Symbol-Asset gerendert und auf dem GPU verteilt. Die App trägt nur die Kosten für das Auslesen eines Werts, um zu entscheiden, wann ausgelöst wird.
  • Die Barrierefreiheit ist abgedeckt: Bewegungsintensive Effekte respektieren die Systemeinstellung „Bewegung reduzieren” ohne projektspezifischen Code2.

Die Effekte, nach Verb

Jeder Effekt benennt, was ein Icon tun kann. Wählen Sie das Verb danach, was die Nutzerin oder der Nutzer in diesem Moment wahrnehmen soll.

.bounce

Ein einzelner elastischer Sprung, konfigurierbar als .up oder .down. Der Effekt signalisiert ein kurzes positives Ereignis: eine Bestätigung, eine eintreffende Benachrichtigung, ein abgeschlossenes Aktualisieren. Er ist das visuelle Äquivalent zu „ja, das ist passiert.” Lösen Sie ihn mit einem value:-Parameter aus: Jedes Mal, wenn sich der Wert ändert, hüpft das Symbol einmal.

@State private var unreadCount = 0

Image(systemName: "bell.badge")
    .symbolEffect(.bounce, value: unreadCount)

Das wertgesteuerte Muster führt den Sprung pro Änderung exakt einmal aus. Keine Zustandsmaschine, keine Mathematik fürs Animations-Timing, keine Auswirkungen auf das Layout.

.pulse

Ein wiederholtes Opazitäts-Pulsieren. Der Effekt signalisiert einen anhaltenden Zustand, der Aufmerksamkeit verdient, ohne alarmierend zu wirken. Häufige Anwendungen: ein Indikator für einen eingehenden Anruf, ein Punkt für „Aufnahme läuft”, ein „Live”-Abzeichen. Das Pulsieren läuft fort, bis es entfernt wird.

Image(systemName: "record.circle")
    .symbolEffect(.pulse, options: .repeating)
    .foregroundStyle(.red)

Die Option .repeating hält das Pulsieren am Leben; ohne .repeating läuft ein einzelner Puls.

.scale

Eine Skalierung nach oben oder unten. Der Effekt betont eine Zustandsänderung in der Bedeutung des Icons: Eine Schaltfläche wird gedrückt, ein Element wird ausgewählt, ein Bedienelement erhält den Fokus. Der Skalierungseffekt unterstützt Richtungsmodifikatoren (.scale.up, .scale.down) und einen bidirektionalen Standard; solange er gehalten wird, bleibt das Symbol skaliert.

Image(systemName: "heart")
    .symbolEffect(.scale, isActive: isLiked)

Der Parameter isActive: ist das alternative Auslösemuster: Solange der Boolean true ist, wird der Effekt gehalten; sobald er auf false umschaltet, wird er aufgelöst. Das Muster passt zu jedem Toggle-Zustand, bei dem die Animation des Icons den Zustand direkt nachverfolgen soll.

.variableColor

Stufenbewusste Farbanimation. Der Effekt lässt die Ebenen des Symbols nacheinander aufleuchten (denken Sie an sich füllende WLAN-Signalbalken oder einen ladenden Akku). Die Verhaltensoptionen bestimmen die Richtung (.iterative läuft vorwärts, .cumulative füllt und hält, .reversing läuft vorwärts und dann rückwärts), und .dimInactiveLayers steuert, ob inaktive Ebenen ausgeblendet werden oder verschwinden.

Image(systemName: "wifi")
    .symbolEffect(
        .variableColor.iterative.reversing.dimInactiveLayers,
        options: .repeating
    )

Den Effekt für variable Farbe verwenden das iOS-Kontrollzentrum, die Einstellungen-App und die meisten Apple-Apps für jedes Symbol für „Signalstärke” oder „Pegelanzeige”. Das Muster ist plattformweit wiedererkennbar, weil die Animation plattformweit geteilt wird.

.replace

Der Effekt, der die Standard-Überblendung von SwiftUI für Symboltausche durchbricht. .contentTransition(.symbolEffect(.replace)) führt einen gestalteten Übergang zwischen zwei Symbolen aus, mit der Option .downUp (das verschwindende Symbol bewegt sich nach unten, das eintreffende nach oben) oder dem standardmäßigen Skalierungs- und Überblendungsverhalten.

@State private var isPlaying = false

Image(systemName: isPlaying ? "pause.circle.fill" : "play.circle.fill")
    .contentTransition(.symbolEffect(.replace))
    .onTapGesture { isPlaying.toggle() }

Das Muster ist das richtige für jede Toggle-Schaltfläche (Play/Pause, Stumm/Ton, Erweitern/Reduzieren, Like/Dislike). Das SwiftUI-Standardverhalten blendet die beiden Bilder ohne symbolbewusstes Feingefühl ineinander über; der Symbol-Effekt-Replace ist ein gestalteter Übergang, der die Struktur des Symbols respektiert.

.appear und .disappear

Bedingte Ein-/Ausblende-Animationen für ein Icon, das in das Layout eintritt oder es verlässt. Die Effekte werden mit den View-Übergängen von SwiftUI kombiniert, damit das Erscheinen des Symbols absichtsvoll wirkt statt abrupt.

Image(systemName: "checkmark.circle.fill")
    .symbolEffect(.appear, isActive: isVisible)

Verwenden Sie sie, wenn das Vorhandensein eines Icons selbst aussagekräftig ist (eine Bestätigungsanzeige, ein Status-Abzeichen, das bei Abschluss erscheint). Für dauerhafte Icons verdienen die Effekte ihren Platz nicht.

.breathe

Eine langsame, atmende Skalierungs- und Opazitätsbewegung (iOS 18+). Der Effekt signalisiert einen ruhigen, ambienten Zustand, der den Blick der Nutzerin oder des Nutzers ohne Dringlichkeit anziehen will. Meditations-Timer, Anzeigen für Ambient-Audio, Leerlaufzustände.

.rotate und .wiggle

Rotations- und Wackel-Animationen (iOS 18+). Rotate passt zu Ladezuständen (ein aktualisierender Pfeil, ein synchronisierendes Zahnrad). Wiggle passt zu Aufforderungen wie „dies ist editierbar, ziehen Sie mich” oder „etwas braucht Ihre Aufmerksamkeit”. Beide bieten Richtungs- und Geschwindigkeitsoptionen.

Die Grammatik: Auslöser und Optionen

Jeder Effekt unterstützt dieselben drei Auslösemuster. Wählen Sie dasjenige, das zum Moment passt.

Wertgesteuert (value:-Parameter). Der Effekt läuft einmal, wenn sich der gebundene Wert ändert. Nützlich für Ereignisse: ein hochzählender Wert, ein Zustandsübergang. Das System liest die Identität des Werts, führt den Effekt aus und setzt zurück.

Zustandsgesteuert (isActive:-Parameter). Der Effekt läuft, solange der gebundene Boolean true ist. Nützlich für gehaltene Zustände: ein Toggle, das pulsieren soll, solange es aktiviert ist; ein Aufnahme-Indikator, der pulsieren soll, solange aufgenommen wird.

Kontinuierlich (options: .repeating). Der Effekt läuft fortlaufend, bis der Modifier entfernt wird. Nützlich für Ambient-Signale: eine Ladeanzeige, ein pulsierendes Live-Abzeichen, ein atmendes Meditations-Icon.

Die Optionen jedes Effekts verfeinern das Verhalten: .speed(_) passt das Tempo der Animation an, .nonRepeating überschreibt den Standard für Effekte, die normalerweise wiederholen, Richtungsmodifikatoren (.up/.down/.iterative/.cumulative/.reversing) formen die Bewegung. Jede Option ist klein; die Kombinationen ergeben ein vollständiges Vokabular.

Der Trick: Symbolvarianten über Zustände hinweg

Ein subtileres Muster nutzt Symboleffekte mit Image(systemName:), das gegen zustandsgetriebene Namen aufgelöst wird. Die Kombination aus zustandsgetriebener Symbolauswahl und .contentTransition(.symbolEffect(.replace)) lässt eine einzelne Image-View ohne manuelle Animationsarbeit zwischen vielen Zuständen animieren.

@State private var connectionState: ConnectionState = .disconnected

var symbol: String {
    switch connectionState {
    case .disconnected: "wifi.slash"
    case .connecting:   "wifi.exclamationmark"
    case .weak:         "wifi.low"
    case .medium:       "wifi.medium"
    case .strong:       "wifi"
    }
}

Image(systemName: symbol)
    .contentTransition(.symbolEffect(.replace))
    .symbolEffect(.variableColor.iterative, options: .repeating, value: connectionState == .connecting)

Fünf Symbolzustände, zwei geschichtete Effekte (Replace-Übergang zwischen den Symbolen, Variable Color während des Verbindens), eine Image-View, kein eigener Animationscode. Das Muster funktioniert, weil SF Symbols als kohärente Familie gestaltet sind; dasselbe Verbindungs-Icon in mehreren Stärken ist eine einzige visuelle Idee, ausgedrückt in mehreren Auflösungen.

Performance: Warum die Kosten faktisch null sind

Symboleffekte werden auf dem GPU animiert und über denselben Render-Pfad ausgeliefert, den SF Symbols bereits für statisches Rendering nutzen. Die Animationen sind im Symbol-Asset selbst kodiert; die App liest einen Wert, das System plant die Animation, der GPU führt sie aus. Es gibt keine Layout-Arbeit pro Frame, kein Hin- und Herwerfen der View-Hierarchie, keine objectWillChange.send()-Kaskade.

Die Kosten, die die Entwicklerin oder der Entwickler trägt, sind die Kosten der Bindung, die den Auslöser steuert: das @State, das @Bindable, die @Observable-Eigenschaft. Diese Kosten existieren unabhängig von der Animation. Die Animation selbst ist im Wesentlichen ein kostenloses Upgrade gegenüber einem statischen Rendering.

Die Kosten zählen für Live-Kamera-UIs, Listenzellen mit vielen Icons und jede View-Hierarchie, in der 60 fps nicht verhandelbar sind. Symboleffekte können großzügig angewendet werden, ohne die Performance-Kosten eines eigenen withAnimation-Blocks; die zugrundeliegende Engine erledigt die Arbeit.

Barrierefreiheit: „Bewegung reduzieren” wird bereits respektiert

Symboleffekte respektieren die Systemeinstellung „Bewegung reduzieren” automatisch. Effekte mit deutlicher Bewegung (.bounce, .scale, .rotate, .wiggle) werden gedämpft oder übersprungen, wenn „Bewegung reduzieren” aktiv ist. Effekte, die hauptsächlich auf Opazität basieren (.pulse, .breathe), bleiben in der Regel bestehen, weil sie keine Probleme mit Bewegungsempfindlichkeit auslösen.

Das Verhalten ist im SwiftUI-Modifier eingebaut; die Entwicklerin oder der Entwickler schreibt nicht für jeden Effekt if accessibilityReduceMotion { ... } else { ... }. Die Apple Human Interface Guidelines geben an, dass die Effekte die Systemeinstellung respektieren, und die SwiftUI-Implementierung entspricht der Dokumentation.

Für Entwicklerinnen und Entwickler, die barrierefreiheitszentrierte Apps bauen (Apps für Nutzerinnen und Nutzer mit vestibulären Störungen, Sehbehinderungen oder Bewegungsempfindlichkeit), sind Symboleffekte das richtige Muster, weil der projektspezifische Aufwand für Barrierefreiheit gleich null ist.

Wenn Symboleffekte ihren Platz nicht verdienen

Drei Fehlermodi, die einen Namen verdienen.

Effekte auf jedem Icon zu jeder Zeit. Eine Ansicht voller pulsierender, atmender und hüpfender Icons ist schwerer zu lesen als eine statische Ansicht. Jeder Effekt sollte einen bestimmten Moment signalisieren; Effekte überall werden zum Rauschen. Die Disziplin lautet, vor dem Hinzufügen zu fragen: „Welchen Moment markiert dieser Effekt?” Lautet die Antwort „das Icon existiert”, streichen Sie den Effekt.

Effekte, die mit dem Inhalt streiten. Eine Liste von Einträgen mit jeweils einem wackelnden Icon sagt nicht „bearbeite mich”; sie sagt „alles ist kaputt.” Der Effekt muss zum Moment im Nutzerfluss passen. Wiggle ist das richtige Verb für ein editierbares Raster im Bearbeitungsmodus, nicht für eine Inhaltsliste im Standardzustand.

Effekte auf Liquid-Glass-Oberflächen ohne Tests. Liquid Glass (behandelt in Liquid Glass SwiftUI Patterns) bricht das Licht hinter sich. Ein hüpfendes oder rotierendes Icon unter Glas erzeugt eine bewegliche Lichtbrechung, die mit dem darunterliegenden Inhalt konkurrieren kann. Testen Sie die Kombination auf echter Geräte-Hardware, bevor Sie sich festlegen.

Die Standarddisziplin: Jeder Effekt ist Opt-in, an einen bestimmten, für die Nutzerin oder den Nutzer bedeutsamen Moment gebunden und auf Barrierefreiheit und Performance getestet. Das Vokabular ist großzügig; das redaktionelle Auge macht den Unterschied.

Was ist neu in SF Symbols 7 (iOS 26)

Die jährliche SF-Symbols-Ausgabe von Apple bringt üblicherweise mehrere tausend neue Symbole und verfeinert bestehende. Für die Symboleffekt-APIs in iOS 26 die konservative Zusammenfassung:

Erweiterte Stufen für variable Farbe. Mehr der bestehenden stufenbewussten Symbole werden mit feingranularerer Variable-Color-Animation ausgeliefert, einschließlich Netzwerk- und Signalstärke-Symbolen, die zuvor zwischen drei Stufen sprangen und nun zwischen fünf wechseln.

Bessere Behandlung von Wiggle und Rotate. Die in iOS 18 hinzugefügten Bewegungseffekte erhielten Verfeinerungen, die die Performance auf leistungsschwächeren Geräten und auf visionOS verbessern, wo Bewegung im 3D-Raum andere Hinweise erfordert.

Symbol-Replace-Übergänge für zusammengesetzte Symbole. Symbole mit mehreren Komponenten (Herz mit Puls, Wolke mit Regen, Person mit Uhr) werden sauberer ersetzt als zuvor und reduzieren den visuellen Bruch beim Übergang zwischen verwandten zusammengesetzten Symbolen.

Die Kernfähigkeiten (die zehn Effekte oben) sind seit SF Symbols 5 (iOS 17) und 6 (iOS 18) ausgereift. Die Ergänzungen in iOS 26 erweitern das Vokabular, statt es neu zu erfinden. Der richtige Adoptionsschritt besteht darin, die bestehenden Verben tief zu lernen, statt auf die nächste Ausgabe zu warten.

Was dieses Muster für iOS-26+-Apps bedeutet

Drei Erkenntnisse.

  1. Die Verben sind keine optionale Dekoration; sie sind ein Vokabular, das die Plattform spricht. Nutzerinnen und Nutzer sehen dieselbe .bounce-Bestätigung in jeder Apple-App. Wer dieselben Verben übernimmt, lässt eine Drittanbieter-App nativ wirken; wer eigene Animationen wählt, die nicht passen, lässt die App plattformfremd wirken. Die Verben sind ein Gewinn für Barrierefreiheit, Performance und Plattformkohärenz zugleich.

  2. Ein Effekt pro Moment. Eine Ansicht, die .bounce für Bestätigungen, .replace für Zustandsumschaltungen und .variableColor für Live-Signale verwendet, nutzt das Vokabular richtig. Eine Ansicht, in der jedes Icon pulsiert, nutzt es schlecht. Die Disziplin ist redaktionell: Welcher Moment verdient den Effekt?

  3. Vertrauen Sie den Standardwerten der Plattform für Barrierefreiheit und Performance. Symboleffekte respektieren „Bewegung reduzieren” automatisch und laufen auf dem GPU zu nahezu null Kosten. Die Arbeit, die Entwicklerinnen und Entwickler sonst leisten müssten (Reduce-Motion-Bedingungen schreiben, Animations-Timing für 60 fps abstimmen), erledigt das Framework bereits.

Das vollständige Apple-Ecosystem-Cluster: typisierte App Intents; MCP-Server; die Routing-Frage; Foundation Models; die Unterscheidung zwischen Runtime und Tooling-LLM; drei Oberflächen; das Single-Source-of-Truth-Muster; zwei MCP-Server; Hooks für die Apple-Entwicklung; Live Activities; die watchOS-Runtime; SwiftUI-Internas; RealityKits räumliches Mentalmodell; SwiftData-Schemadisziplin; Liquid-Glass-Muster; Multi-Plattform-Auslieferung; die Plattform-Matrix; Vision-Framework; worüber ich mich weigere zu schreiben. Der Hub befindet sich unter Apple Ecosystem Series. Für den breiteren Kontext rund um iOS mit KI-Agenten siehe den iOS Agent Development Guide.

FAQ

Was ist der Unterschied zwischen .symbolEffect und .contentTransition(.symbolEffect(.replace))?

.symbolEffect(...) führt eine Animation auf einem einzelnen Symbol aus, das seine Identität nicht ändert (die Glocke heißt weiterhin „Glocke”, hüpft aber). .contentTransition(.symbolEffect(.replace)) führt einen gestalteten Übergang zwischen zwei unterschiedlichen Symbolen aus (aus der Glocke wird eine durchgestrichene Glocke). Das erste dient der Betonung eines Zustands; das zweite dem Austausch der Symbolidentität.

Funktionieren Symboleffekte auf visionOS?

Ja. Symboleffekte werden auf visionOS auf dieselbe Weise gerendert, wobei die Bewegungsanpassung des Systems die räumliche Umgebung respektiert. Wiggle- und Rotate-Effekte sind auf visionOS so abgestimmt, dass sie sich auf räumliche Distanz richtig anfühlen; Entwicklerinnen und Entwickler schreiben dafür keinen plattformspezifischen Code.

Kann ich eigene Symboleffekte schreiben?

Die Effektmenge des Frameworks ist geschlossen; es lässt sich kein neuer Effekttyp definieren. Die Menge ist großzügig genug, dass eigene Effekte selten nötig sind. Für Animationen jenseits des Symbolvokabulars sind die nativen Animations-Primitiven von SwiftUI (.animation, withAnimation, Transaction, eigene Animatable-Views) das richtige Werkzeug, allerdings müssen Sie die Kosten pro Frame selbst verwalten.

Wirkt sich die Verwendung von Symboleffekten auf das App-Store-Review aus?

Nein. Symboleffekte sind eine öffentliche SwiftUI-API und werden identisch zu jeder anderen SwiftUI-Nutzung geprüft. Die Human Interface Guidelines fördern ihre Nutzung aktiv; eine App, die den Richtlinien folgt, hat weniger Review-Überraschungen als eine, die für denselben Zweck eigene Animationssysteme baut.

Warum läuft mein .bounce-Effekt nicht, wenn ich den Wert ändere?

Drei häufige Ursachen. Erstens muss der Wert tatsächlich seine Identität ändern (@State Int von 0 auf 1, nicht derselbe Int 0, der erneut zugewiesen wird). Zweitens spielt die Modifier-Reihenfolge eine Rolle: .symbolEffect(.bounce, value: foo) muss auf das Image angewendet werden, nicht auf einen umschließenden Button oder ein HStack. Drittens läuft der Effekt einmal pro Identitätsänderung; schnelle Änderungen werden zusammengefasst. Für sich wiederholende oder gehaltene Effekte verwenden Sie .repeating oder isActive: statt value:.

Quellen


  1. Apple Developer Documentation: SymbolEffect und .symbolEffect(_:options:value:) in SwiftUI. 

  2. Apple Human Interface Guidelines: Motion. Die Systemeinstellungen für Bewegung („Bewegung reduzieren”) werden von SF-Symbol-Effekten automatisch berücksichtigt. 

Verwandte Beiträge

What SwiftUI Is Made Of

SwiftUI is a result-builder DSL on top of a value-typed View tree. Once the substrate is visible, AnyView, Group, and Vi…

17 Min. Lesezeit

Liquid Glass in SwiftUI: Three Patterns From Shipping Return on iOS 26

Apple's Liquid Glass is a one-line SwiftUI API. Three patterns from Return go beyond .glassEffect(): glass on text via C…

19 Min. Lesezeit

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 Min. Lesezeit