SwiftUI Tutorial: Einführung in Bindings

von @ralfebert · aktualisiert am 1. März 2022

Das Tutorial führt in die Verwendung von Bindings und dem @Binding-Property-Wrapper in SwiftUI ein.

Sofern Du noch nicht mit SwiftUI gearbeitet hast, empfehle ich zuvor das Tutorial: Einführung in SwiftUI durchzuarbeiten.

  1. Verwende für dieses Tutorial die aktuelle Xcode-Version. Dieses Tutorial wurde zuletzt getestet am 1. März 2022 mit Xcode 13.

  2. Lade für dieses Tutorial den Start-Stand von dem Projekt Shapes. Mit diesem kannst Du anhand eines praktischen Beispiels direkt die Verwendung von Bindings ausprobieren.

  3. Mache Dich mit dem Projekt vertraut. Es enthält einen Datentyp Circle zur Berechnung von Radius, Durchmesser und Fläche von einem Kreis und ein ShapeView, welches diese Werte anzeigt. Für die Darstellung eines Feldes wurde ein separates View NumberValueView extrahiert:

    Beispiel-App Shapes
  4. Füge in NumberValueView zusätzlich zu den Text-Labels ein TextField hinzu. Gib als format .number an und verwende den textFieldStyle-Modifier, um das Textfeld mit Rahmen anzuzeigen:

    struct NumberValueView: View {
        var imageName: String
        var value: Double
    
        var body: some View {
            HStack {
                Image(imageName)
                Text("\(value)")
                TextField("Value", value: self.value, format: .number)
            }
        }
    }
    
    struct NumberValueView_Previews: PreviewProvider {
        static var previews: some View {
            NumberValueView(imageName: "diameter", value: 5)
        }
    }
    

    Dies führt zu einem Fehler, da für value ein Binding erwartet wird. Ein Binding erlaubt SwiftUI den Wert zu holen als auch bei Änderungen zu setzen.

  5. Behebe dieses Problem, indem Du die Eigenschaft value zunächst einmal testweise als @State deklarierst (dieser Property Wrapper macht die Eigenschaft veränderbar). Eine solche Eigenschaft stellt als sog. projected value (beginnend mit $-Zeichen) ein Binding für die Eigenschaft bereit - verwende diese für den value des Textfeldes:

    struct NumberValueView: View {
        var imageName: String
        @State var value: Double
    
        var body: some View {
            HStack {
                Image(imageName)
                Text("\(value)")
                TextField("Value", value: $value, format: .number)
            }
        }
    }
    
  6. Starte die App und teste das Verhalten. Wird in einem Textfeld getippt, wird der Wert innerhalb von NumberValueView übernommen. Dies ist sichtbar an dem noch vorhandenen Label: Es wird aktualisiert, weil die Änderung an der @State-Eigenschaft die Aktualisierung des Views auslöst. Der Wert wird allerdings nicht an das übergeordnete ShapeView weitergegeben:

  7. Deklariere die NumberValueView-Eigenschaft value als @Binding - damit wird der Wert nicht mehr im View gehalten sondern ein externer Wert wird per Binding referenziert:

    struct NumberValueView: View {
        var imageName: String
        @Binding var value: Double
    
        // …
    }
    
  8. Verwende im ShapeView für die circle-Eigenschaft @State um diese als View-Zustand zu deklarieren. Mit dem $-projected value kann nicht nur der Wert sondern auch dessen Eigenschaften als Binding referenziert werden:

    struct ShapeView: View {
        @State var circle = Circle(radius: 1)
    
        var body: some View {
            Form {
                NumberValueView(imageName: "radius", value: $circle.radius)
                NumberValueView(imageName: "diameter", value: $circle.diameter)
                NumberValueView(imageName: "area", value: $circle.area)
            }
        }
    
    }
    
  9. Im PreviewProvider des ShapeView muss nun auch ein Binding übergeben werden. Für den Zweck der Vorschau kann hier Binding.constant verwendet werden:

    struct NumberValueView_Previews: PreviewProvider {
        static var previews: some View {
            NumberValueView(imageName: "diameter", value: .constant(5))
        }
    }
    

    (alternativ könnte auch eine statische @State-Eigenschaft für den PreviewProvider verwendet werden, um ein veränderliches Binding übergeben zu können)

  10. Entferne das unnötige Label für den Wert in NumberValueView und teste das Verhalten der App:

Weitere Informationen