@Binding ist ein Property Wrapper in SwiftUI, der eine Referenz auf Daten erstellt, die einer anderen Komponente gehören. Binding speichert den Wert nicht selbst — es bietet nur Zugriff auf die bestehende Quelle der Wahrheit durch die $-Projektion. Laut der Apple Developer Documentation (2025) bietet Binding eine reaktive bidirektionale Kommunikation zwischen Eltern- und Kind-View ohne direkten Datenbesitz. @Binding ist der Schlüsselmechanismus, um veränderlichen Zustand in der Hierarchie nach unten zu reichen.
Wichtige Punkte
@Binding ist ein Property Wrapper, der eine bidirektionale Verbindung zwischen einer in der Eltern-View gespeicherten Eigenschaft und einer Kind-Komponente erstellt. Der Hauptunterschied zwischen Binding und @State: Binding besitzt die Daten nicht. Es liest und schreibt Werte nur durch die wahre Quelle — @State, @StateObject oder ein anderes Binding im Elternteil. Ohne Binding könnten Kind-Views den Zustand des Vorfahren nicht ohne Callbacks oder Delegierte ändern.
Binding ist als Struktur mit zwei Eigenschaften implementiert: wrappedValue (der aktuelle Wert) und projectedValue (das Binding selbst, zugänglich über $). Wenn eine Kind-View wrappedValue über Binding ändert, überträgt SwiftUI die Änderung an die Datenquelle und zeichnet alle abhängigen Views neu. Dies geschieht synchron innerhalb des aktuellen Aktualisierungszyklus.
Ein wichtiges Merkmal: @Binding ist nicht auf die Übergabe auf einer Ebene beschränkt. Binding kann über mehrere Hierarchieebenen weitergegeben werden — jede Kind-Komponente erhält eine Referenz auf dieselbe Datenquelle. Eine Änderung auf jeder Ebene löst eine einzige Aktualisierung aller gebundenen Views aus.
Der Mechanismus der bidirektionalen Bindung durch @Binding basiert auf Property-Wrapper-Projektionen. Wenn ein Elternteil @State var value: T deklariert, generiert SwiftUI automatisch die $value-Projektion vom Typ Binding<T>. Durch die Übergabe von $value an eine Kind-Komponente mit @Binding var value: T verbinden Sie beide Views mit derselben Speicherzelle. Jedes Schreiben über Binding in der Kind-View löst eine Neuzeichnung beider Komponenten aus.
struct SliderContainer: View {
@State private var value: Double = 0.5
var body: some View {
VStack {
Text("Value: \(value)")
SliderView(value: $value)
}
}
}
struct SliderView: View {
@Binding var value: Double
var body: some View {
Slider(value: $value, in: 0...1)
}
}
Im Beispiel besitzt SliderContainer @State value, und SliderView erhält das Binding über $value. Der Slider innerhalb von SliderView ist an dieses Binding gebunden. Beim Ziehen des Schiebereglers ändert Slider den Wert über Binding, was automatisch @State in SliderContainer aktualisiert, und beide Views zeigen die aktuelle Zahl an. Die gesamte Kette funktioniert ohne einen einzigen Callback oder Benachrichtigung.
Um ein Binding aus @StateObject oder @ObservedObject zu erstellen, wird dieselbe Projektion verwendet: $object.property ergibt Binding<PropertyType>. Dies ermöglicht das Übergeben einzelner Eigenschaften von ObservableObject an Kind-Views, ohne das gesamte Objekt zu übergeben. Dieser Ansatz bietet eine engere Kopplung und verhindert unnötige Neuzeichnungen.
Vor SwiftUI war die Standardmethode, Änderungen in der Hierarchie nach oben zu reichen, Callbacks und Delegierte: der Elternteil übergab einen Closure, die Kind-Komponente rief ihn bei Änderung auf. @Binding bietet eine Alternative mit weniger Code und einer deklarativeren Syntax. Anstatt einen Abschluss-Closure zu übergeben, übergeben Sie einfach $stateValue.
| Kriterium | @Binding | Callbacks |
|---|---|---|
| Code | Eine Annotation + $ | Closure + Aufruf |
| Mehrebenen | Automatisch | Closure-Kette |
| Testen | Binding(value:constant) | Mock-Closures |
| Lesbarkeit | Hoch | Mittel |
| Flexibilität | Nur Daten | Beliebige Logik |
Verwenden Sie @Binding, wenn die Kind-View nur einen Wert lesen und ändern muss. Wenn bei Änderung Nebeneffekte erforderlich sind (Validierung, Protokollierung, Netzwerkanfrage), kombinieren Sie Binding mit einem Callback: übergeben Sie Binding für Daten und einen Closure für Ereignisse. Beispielsweise kann ein TextField an ein Binding gebunden werden, während onChange die Validierung auslöst.
@Binding wird in mehreren typischen Szenarien verwendet. Das erste — benutzerdefinierte Steuerelemente: Schalter, Schieberegler, Farbwähler und andere interaktive Elemente akzeptieren Binding zur bidirektionalen Synchronisation. Das zweite — modale Fenster: das Sheet-Anzeigeflag wird als Binding übergeben, sodass die Kind-View sich selbst über presentationMode oder direkte Einstellung schließen kann.
Das dritte Muster — Formulare mit Trennung. Wenn ein Formular aus vielen Feldern besteht, kann jedes Feld in eine separate Komponente extrahiert werden, die ein Binding für seinen Wert akzeptiert. Dies vereinfacht das Testen und die Wiederverwendung von Feldern in verschiedenen Formularen. Die Eltern-Komponente bleibt der alleinige Besitzer des gesamten Formularmodells.
struct FormField: View {
let title: String
@Binding var text: String
var body: some View {
VStack(alignment: .leading) {
Text(title).font(.caption)
TextField("Enter \(title.lowercased())", text: $text)
.textFieldStyle(.roundedBorder)
}
}
}
Die FormField-Komponente akzeptiert einen Titel und ein Binding auf einen String. Sie zeigt ein Label und ein TextField an, das an das übergebene Binding gebunden ist. Jedes Formular kann FormField mehrmals verwenden, indem $property für jedes Feld übergeben wird. Dies reduziert Markup-Duplikation und zentralisiert die Gestaltung von Textfeldern.
SwiftUI ermöglicht die manuelle Erstellung von Binding über den Initialisierer Binding(get:set:). Dies ist nützlich, wenn beim Lesen oder Schreiben eines Werts Logik hinzugefügt werden muss. Beispielsweise kann ein Binding erstellt werden, das eine Zahl vor dem Speichern formatiert, oder ein Binding, das den Wert bei jeder Änderung mit einem entfernten Server synchronisiert.
struct ValidatedField: View {
@State private var email: String = ""
var emailBinding: Binding<String> {
.init(
get: { email },
set: { email = $0.lowercased().trimmingCharacters(in: .whitespaces) }
)
}
var body: some View {
TextField("Email", text: emailBinding)
}
}
Im Listing wandelt das benutzerdefinierte emailBinding automatisch Text in Kleinbuchstaben um und entfernt Leerzeichen bei jeder Änderung. Das TextField verwendet dieses Binding anstatt direkt an $email zu binden. Dieser Ansatz zentralisiert Validierung und Datentransformation innerhalb des Bindings, ohne den Code mit onChange-Handlern zu überladen.
Der erste und häufigste Fehler ist das Übergeben eines Werts anstelle eines Bindings. Wenn eine Kind-Komponente @Binding var text: String deklariert und der Elternteil text (ohne $) übergibt, gibt der Compiler einen Fehler aus: Cannot convert value of type 'String' to expected argument type 'Binding<String>'. Die Lösung — verwenden Sie immer das $-Präfix beim Übergeben: $text.
Der zweite Fehler — Binding auf schreibgeschützte Daten. Wenn die Kind-View nur einen Wert lesen muss, verwenden Sie nicht @Binding — ein einfaches let oder @State vom Elternteil reicht aus. Binding impliziert Schreibfähigkeit, und übermäßige Änderungsberechtigungen erschweren das Debugging und verletzen das Prinzip der minimalen Rechte.
Das dritte Problem — Binding.constant in der Produktion. Binding.constant(value) erstellt eine Dummy-Bindung ohne Rückmeldung — Änderungen werden ignoriert. Verwenden Sie constant nur zum Prototyping und für Vorschauen (Xcode Previews), aber niemals in echtem Code. Für Tests verwenden Sie Binding(get:set:) mit kontrolliertem Verhalten.
Häufig gestellte Fragen
@State besitzt die Daten und verwaltet ihre Speicherung im Heap. @Binding referenziert nur den vorhandenen Zustand ohne Besitz. @State ist immer privat, @Binding ist ein Eingabeparameter der Kind-View.
Ja, über den Initialisierer Binding(get:set:) oder Binding.constant(value). Binding kann auch von @StateObject über die $object.$property-Projektion und von Publisher über Binding(get:set:) innerhalb von Subscribe bezogen werden.
@Binding wird über eine Kette übergeben: jede Zwischenkomponente deklariert @Binding und gibt es über $ weiter. Alle Ebenen referenzieren dieselbe Datenquelle in der Root-View.
Binding.constant erstellt einen stummen Wrapper — der Setter ignoriert neue Werte. Es ist nur zum Prototyping und für SwiftUI Previews gedacht, wo keine Rückmeldung von der Kind-Komponente erforderlich ist.
Ja, Binding<T?> wird unterstützt. Wenn Sie Binding<String?> übergeben, kann die Kind-View nil setzen. Dies ist praktisch für optionale Formularfelder oder Zustände mit Zurücksetzungsoption.
Zusammenfassung
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.
Lesen Sie auch