SwiftUI So instanziieren Sie PreviewProvider, wenn View @Binding im Initialisierer erfordert

10

Mit SwiftUI (Xcode 11.1) habe ich einige Ansichten mit 2-Wege-Bindungen eingerichtet (mit @Binding ). Die bidirektionale Aktualisierung funktioniert hervorragend.

Wie kann ich jedoch die Ansicht über den PreviewProvider instanziieren?

Zum Beispiel:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

        return VStack {
            Text("Add Project View")
            Button("Dismiss") {
                self.showModal = false
            }
        }
    }
}

Ich kann das nicht tun, weil "wahr" keine Bindung ist:

struct AddProjectView_Previews: PreviewProvider {
    static var previews: some View {
        AddProjectView(showModal: true)
    }
}

Und ich kann dies nicht tun, weil " Property Wrapper für lokale Eigenschaften noch nicht unterstützt werden ":

struct AddProjectView_Previews: PreviewProvider {
    static var previews: some View {
        @Binding var show = true
        return AddProjectView(showModal: $show)
    }
}

Wie machen wir das?

Vielen Dank!!

Zeichner
quelle

Antworten:

15

.constant ist genau dafür gedacht:

/// Erstellt eine Bindung mit einem unveränderlichen value.

struct AddProjectView: View {
    @Binding public var showModal: Bool
    var body: some View {
        return VStack {
            Text("Add Project View")
            Button("Dismiss") {
                self.showModal = false
            }
        }
    }
}

struct AddProjectView_Previews: PreviewProvider {
    static var previews: some View {
        AddProjectView(showModal: .constant(true))
    }
}
Superpuccio
quelle
Perfekt! -- Genial!
Zeichner
5

Sie müssen es in Ihrer Vorschau als @State deklarieren.

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

     static var previews: some View {
         AddProjectView(showModal: $showModal)
     }
}

Denken Sie auch daran, dass es statisch sein muss, da es in einer statischen Funktion verwendet wird.

LuLuGaGa
quelle
1
Das Verhalten in XCode 11.3 entspricht praktisch dem von .constant(false). Wenn Sie also die Live-Vorschau verwenden, kann der Wert nicht geändert werden.
Fabian Streitel
4

Wenn Sie nur einen konstanten Wert benötigen , verwenden Sie .constant(VALUE):

struct YourView_Previews: PreviewProvider {

    static var previews: some View {
        YourView(yourBindingVar: .constant(true))
    }

}

Wenn Sie einen Wert benötigen, der in der Live-Vorschau geändert werden kann , verwende ich gerne diese Hilfsklasse:

struct BindingProvider<StateT, Content: View>: View {

    @State private var state: StateT
    private var content: (_ binding: Binding<StateT>) -> Content

    init(_ initialState: StateT, @ViewBuilder content: @escaping (_ binding: Binding<StateT>) -> Content) {
        self.content = content
        self._state = State(initialValue: initialState)
    }

    var body: some View {
        self.content($state)
    }
}

Verwenden Sie es so:

struct YourView_Previews: PreviewProvider {

    static var previews: some View {
        BindingProvider(false) { binding in
            YourView(yourBindingVar: binding)
        }
    }

}

Auf diese Weise können Sie das Ändern der Bindung in der Live-Vorschau testen.

Fabian Streitel
quelle
Sie haben keine Ahnung, wie Ihre Antwort mir geholfen hat, besseren Code zu erstellen. Tausend Dank. Ich lerne immer noch SWIFTUI und BindingProvider, den Sie geschrieben haben, übersteigt mein begrenztes schnelles Wissen. Ich bekomme ein Gefühl dafür, aber verstehe 100% nicht. Danke trotzdem.
GrandSteph
Froh, dass ich Helfen kann! Weiter so und weiter lernen: D
Fabian Streitel