Property Wrapper: Schlüsselkonzepte, Syntax und Beispiele in SwiftUI

Autor: IT Sectr Veröffentlicht: 2026-06-19 Lesezeit: 8 Min.

Property Wrapper ist ein Swift-Mechanismus, der dem Zugriff und der Änderung von Eigenschaften eine Logikebene hinzufügt, ohne Code zu duplizieren. In SwiftUI wurden Property Wrappers zur Grundlage der Zustandsverwaltung von Views: @State, @Binding, @ObservedObject, @StateObject und @Environment. Laut der Swift-Dokumentation (2025) reduzieren Eigenschaftsverpackungen den Boilerplate-Code in Projekten um durchschnittlich 40%. Das Verständnis von Property Wrapper ist für jeden iOS-Entwickler unerlässlich, um effektiv mit dem Framework zu arbeiten.

Wichtige Erkenntnisse

  • Property Wrapper — ein syntaktisches Konstrukt von Swift, das dem Getter und Setter einer Eigenschaft Logik hinzufügt
  • @State — ein Wrapper für lokalen Zustand, der zu einer einzelnen View gehört
  • @Binding — eine bidirektionale Verbindung zu einer Datenquelle aus der übergeordneten View
  • @ObservedObject — Beobachtung eines externen ObservableObject ohne Besitz
  • @StateObject — Erstellung und Besitz eines ObservableObject auf Ebene der aktuellen View

Was ist Property Wrapper?

Property Wrapper — ein Sprachkonstrukt von Swift, eingeführt in Version 5.1, das es ermöglicht, die Zugriffslogik einer Eigenschaft in einem separaten Typ zu kapseln. Anstatt in jeder Klasse wiederholt Getter und Setter zu schreiben, deklariert der Entwickler den Wrapper einmal und wendet ihn über die @-Annotation vor dem Typ an. Swift umschließt die Eigenschaft automatisch mit dem angegebenen Typ und ruft beim Lesen und Schreiben dessen Methoden wrappedValue und projectedValue auf. Laut Apple (WWDC 2019) wurden Property Wrappers zu einer Schlüsselabstraktion für SwiftUI.

Ein Eigenschaftswrapper ist eine Struktur oder Klasse mit dem Attribut @propertyWrapper. Im Inneren muss ein solcher Typ die Eigenschaft wrappedValue implementieren, die den tatsächlichen Wert zurückgibt und setzt. Der Swift-Compiler ersetzt Zugriffe auf die ursprüngliche Eigenschaft durch Aufrufe von wrappedValue und verbirgt die Implementierung vollständig vor dem aufrufenden Code. Zusätzlich kann projectedValue definiert werden — eine Projektion, die über das $-Symbol zugänglich ist.

Der Vorteil von Property Wrappers liegt in der Wiederverwendbarkeit der Logik. Beispielsweise kann man einen Wrapper für E-Mail-Validierung, Wert-Zwischenspeicherung oder Speichersynchronisation erstellen — und auf jede Eigenschaft im Projekt anwenden. In SwiftUI wird dieses Konzept überall verwendet: Jeder Zustandsverwaltungsmechanismus ist als separater Property Wrapper implementiert.

Wie funktioniert Property Wrapper in Swift?

Bei der Deklaration einer Eigenschaft mit der Annotation @WrapperType var value: T transformiert der Swift-Compiler den Code. Er erstellt eine Instanz von WrapperType und generiert den Zugriff auf die Eigenschaft über wrappedValue. Der Quellcode let x = value wird zu let x = _value.wrappedValue, und value = newValue wird zu _value.wrappedValue = newValue. Diese Transformation erfolgt zur Compile-Zeit ohne Laufzeit-Overhead.

swift
@propertyWrapper
struct Capitalized {
    private var text: String

    var wrappedValue: String {
        get { text }
        set { text = newValue.capitalized }
    }

    init(initialValue: String) {
        text = initialValue.capitalized
    }
}

Das Listing zeigt den Wrapper Capitalized, der eine Zeichenkette automatisch in ein Format mit Großbuchstaben umwandelt. Bei der Zuweisung eines Werts ruft der Setter vor dem Speichern capitalized auf. Jede Eigenschaft mit der @Capitalized-Annotation speichert nun nur noch korrekt formatierten Text. Dieser Ansatz eliminiert vollständig die Duplizierung von Validierungs- und Formatierungscode.

Die Projektion (projectedValue) — ein zusätzlicher Kommunikationskanal, der über das Präfix $ zugänglich ist. In SwiftUI wird diese Funktion überall verwendet: $state liefert Binding, und $observedObject gibt Published.Publisher zurück. Die Projektion ermöglicht es dem Wrapper, eine erweiterte Schnittstelle bereitzustellen, ohne den grundlegenden Zugriff auf den Wert zu ändern.

Wichtigste Property Wrappers in SwiftUI

SwiftUI enthält fünf integrierte Property Wrappers für die Zustandsverwaltung: @State, @Binding, @ObservedObject, @StateObject und @Environment. Jeder löst eine spezifische Aufgabe und wird in verschiedenen Szenarien verwendet. @State ist für einfache lokale Daten gedacht, @Binding — zum Übergeben eines Datenverweises an untergeordnete Views, @ObservedObject und @StateObject — für komplexe Objekte, @Environment — für Systemwerte aus der Hierarchie.

WrapperZweckBesitz
@StateLokaler Zustand einer einzelnen ViewAktuelle View
@BindingBidirektionale Verbindung mit der Eltern-ViewEltern-View
@ObservedObjectBeobachtung eines externen ObjektsExterner Besitzer
@StateObjectErstellung eines ObservableObjectAktuelle View
@EnvironmentSystemwerte aus der HierarchieSwiftUI-Umgebung

Die Wahl eines bestimmten Property Wrapper hängt von der Datenquelle und ihrem Lebenszyklus ab. Wenn die Daten zu einer einzelnen View gehören und von untergeordneten Komponenten nicht benötigt werden — verwenden Sie @State. Wenn eine untergeordnete View die Daten der Eltern-View ändern muss — verwenden Sie @Binding. Für Objekte, die in mehreren Views verwendet werden, sind @ObservedObject und @StateObject geeignet.

@State: Lokaler Zustand einer View

@State ist ein Property Wrapper zum Speichern des lokalen Zustands innerhalb einer einzelnen View. SwiftUI verwaltet automatisch den Speicher für @State-Eigenschaften und zeichnet die View bei jeder Änderung neu. @State ist für einfache Typen (String, Int, Bool, enum) und Strukturen geeignet, die ausschließlich zur aktuellen View gehören. Wenn sich der Wert ändert, führt SwiftUI die body-Eigenschaft erneut aus.

swift
struct CounterView: View {
    @State private var count: Int = 0

    var body: some View {
        VStack {
            Text("Anzahl: \(count)")
            Button("Erhöhen") {
                count += 1
            }
        }
    }
}

Im Beispiel speichert die @State-Eigenschaft count den aktuellen Zählerwert. SwiftUI erstellt einen Speicherbereich für diese Eigenschaft auf dem Heap und bindet ihn an den Lebenszyklus von CounterView. Wenn der Button gedrückt wird, erhöht sich count um 1, SwiftUI erkennt die Änderung und führt body erneut aus, um den neuen Wert anzuzeigen. Wichtig: @State sollte nicht für komplexe Referenztypen verwendet werden — dafür sind @StateObject und @ObservedObject vorgesehen.

@Binding: Bidirektionale Verbindung zwischen Views

@Binding erstellt einen Verweis auf eine Datenquelle, die zu einer anderen View gehört. Binding speichert selbst keinen Wert — es liest und schreibt Daten über @State, @StateObject oder ein anderes vom Elternteil übergebenes Binding. Dies ermöglicht es untergeordneten Komponenten, den Zustand des Vorfahren zu ändern, ohne die Daten direkt zu besitzen und ohne Callbacks.

swift
struct ToggleSwitch: View {
    @Binding var isOn: Bool

    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

Im Listing erhält ToggleSwitch @BindingBool von der übergeordneten View. Der Elternteil erstellt @State var isToggleOn = false und übergibt $isToggleOn an den Initialisierer von ToggleSwitch. Wenn der Benutzer den Schalter innerhalb der untergeordneten View umlegt, wird die Änderung sofort im @State des Elternteils reflektiert. Der Binding-Mechanismus eliminiert vollständig die Notwendigkeit von Delegaten oder Closures, um Änderungen in der Hierarchie nach oben zu reichen.

@ObservedObject und @StateObject: Externe Daten

@ObservedObject ist ein Property Wrapper zum Beobachten einer von außen übergebenen ObservableObject-Instanz. Die View besitzt dieses Objekt nicht — es wird in der übergeordneten Komponente erstellt oder über Environment injiziert. Wenn sich eine @Published-Eigenschaft innerhalb des ObservableObject ändert, zeichnet SwiftUI alle über @ObservedObject abonnierten Views neu.

@StateObject — ein Wrapper zum Erstellen und Besitzen eines ObservableObject direkt in der View. Im Gegensatz zu @ObservedObject garantiert @StateObject eine einzelne Instanz des Objekts für den gesamten Lebenszyklus der View. Selbst wenn SwiftUI die View-Struktur neu erstellt (was häufig vorkommt), bewahrt @StateObject das vorhandene Objekt und ruft den Initialisierer nicht erneut auf.

swift
class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
}

struct ProfileView: View {
    @StateObject var settings = UserSettings()

    var body: some View {
        ChildProfileView(settings: settings)
    }
}

struct ChildProfileView: View {
    @ObservedObject var settings: UserSettings

    var body: some View {
        Text("Hallo, \(settings.username)")
    }
}

Im Beispiel erstellt ProfileView UserSettings über @StateObject und wird zum Besitzer des Objekts. ChildProfileView erhält dieselbe Instanz über @ObservedObject — beobachtet, verwaltet aber nicht den Lebenszyklus. Wenn sich username ändert, werden beide Views aktualisiert. Wenn ChildProfileView statt @ObservedObject @StateObject verwendet hätte, würde bei jedem Rendern eine neue Instanz mit dem Anfangswert erstellt.

Die Schlüsselregel: @StateObject wird in der View verwendet, die das Objekt erstellt (Quelle der Wahrheit), während @ObservedObject in der View verwendet wird, die ein bereits erstelltes Objekt vom Elternteil erhält. Ein Verstoß gegen diese Regel führt zu Zustandsverlust oder unerwarteter Neuerstellung von Daten.

Erstellung eines benutzerdefinierten Property Wrapper

Swift ermöglicht die Erstellung benutzerdefinierter Property Wrappers für jede wiederholte Zugriffslogik auf Eigenschaften. Deklarieren Sie einfach eine Struktur oder Klasse mit dem Attribut @propertyWrapper und implementieren Sie wrappedValue. Unten wird der Wrapper UserDefaultsWrapper gezeigt, der den Wert automatisch mit UserDefaults synchronisiert.

swift
@propertyWrapper
struct UserDefaultsWrapper<T> {
    let key: String
    let defaultValue: T

    var wrappedValue: T {
        get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
        set { UserDefaults.standard.set(newValue, forKey: key) }
    }
}

struct AppConfig {
    @UserDefaultsWrapper(key: "theme", defaultValue: "light")
    var theme: String
}

Der Wrapper UserDefaultsWrapper verwendet einen generischen Typ T, um mit jedem von UserDefaults unterstützten Datentyp zu arbeiten. Der Getter liest den Wert per Schlüssel, der Setter schreibt ihn. Die Anwendung von @UserDefaultsWrapper(key:defaultValue:) auf die Eigenschaft theme bindet sie automatisch an den Speicher — die gesamte UserDefaults-Logik ist innerhalb des Wrappers verborgen. Dies ist ein typisches Beispiel für die Reduzierung von Boilerplate-Code mit Property Wrappers.

Bei der Erstellung benutzerdefinierter Wrapper ist es wichtig, die Leistung zu berücksichtigen. Da der Getter und Setter bei jedem Zugriff auf die Eigenschaft aufgerufen werden, sollten keine schweren I/O-Operationen in wrappedValue platziert werden. Für asynchrone Datenspeicherung ist es besser, Property Wrappers mit ObservableObject und @Published zu kombinieren.

Häufig gestellte Fragen

Was ist der Unterschied zwischen @State und @StateObject?

@State ist für einfache Typen (String, Int, Bool) und Strukturen konzipiert, während @StateObject für Referenztypen gedacht ist, die ObservableObject implementieren. @State speichert den Wert direkt in SwiftUI, @StateObject verwaltet eine Klasseninstanz auf dem Heap.

Kann @Binding ohne @State verwendet werden?

Ja, @Binding kann aus @StateObject, @ObservedObject oder einem anderen Binding über die $-Projektion erstellt werden. Binding kann auch von ObservableObject über $object.$publishedProperty oder von InlineBinding über Binding.constant(value) initialisiert werden.

Welchen Property Wrapper für Daten wählen, die in der gesamten Anwendung verwendet werden?

Für globale Daten verwenden Sie @EnvironmentObject oder injizieren Sie ObservableObject über EnvironmentValues. @StateObject eignet sich für die Root-View mit anschließender Weitergabe über @ObservedObject an untergeordnete Komponenten.

Warum kann @ObservedObject Daten neu erstellen?

@ObservedObject besitzt das Objekt nicht — wenn die übergeordnete View neu erstellt wird und eine neue Instanz übergibt, wechselt @ObservedObject zu dieser. Um Zustandsverlust zu vermeiden, sollte die besitzende View @StateObject verwenden.

Kann ein Property Wrapper für asynchrone Operationen erstellt werden?

Ja, aber einfacher ist die Kombination von ObservableObject mit @Published und asynchronen Funktionen innerhalb der Klasse. Property Wrapper ist von Natur aus synchron — wrappedValue wird bei jedem Zugriff berechnet, was für langlebige Operationen ungeeignet ist.

Zusammenfassung

  • Property Wrapper — ein syntaktisches Konstrukt von Swift 5.1 zur Kapselung der Zugriffslogik von Eigenschaften ohne Code-Duplizierung
  • @State — lokaler Zustand für einfache Typen, zeichnet die View bei Änderung automatisch neu
  • @Binding — ein Verweis auf Daten der übergeordneten View ohne Besitz, zugänglich über die $-Projektion
  • @StateObject — Besitz von ObservableObject mit Garantie einer einzelnen Instanz pro Lebenszyklus
  • @ObservedObject — Beobachtung eines von der übergeordneten Komponente übergebenen ObservableObject
  • @Environment — Zugriff auf SwiftUI-Systemumgebungsobjekte
  • Benutzerdefinierte Wrapper werden über das @propertyWrapper-Attribut und die Implementierung von wrappedValue erstellt

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch