SwiftUI Come creare un'istanza di PreviewProvider quando View richiede @Binding nell'inizializzatore


10

Con SwiftUI (Xcode 11.1), ho alcune viste configurate con collegamenti a 2 vie (usando @Binding ). L'aggiornamento bidirezionale funziona alla grande.

Tuttavia, come posso creare un'istanza della vista da PreviewProvider?

Per esempio:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

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

Non posso farlo, perché "true" non è un binding:

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

E non posso farlo perché " I wrapper di proprietà non sono ancora supportati sulle proprietà locali ":

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

Come facciamo questo?

Grazie!!

Risposte:


15

.constant è pensato esattamente per questo:

/// Crea un'associazione con un immutabile 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))
    }
}

Perfetto! -- Eccezionale!
Estratto il

5

Devi dichiararlo come @State nella tua anteprima.

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

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

Ricorda anche che deve essere statico in quanto viene utilizzato in una funzione statica.


1
Il comportamento in XCode 11.3 è effettivamente lo stesso dell'utilizzo .constant(false), ovvero se si utilizza l'anteprima dal vivo, il valore non può essere modificato.
Fabian Streitel,

4

Se hai solo bisogno di un valore costante , usa .constant(VALUE):

struct YourView_Previews: PreviewProvider {

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

}

Se hai bisogno di un valore che può essere modificato nell'anteprima dal vivo , mi piace usare questa classe di supporto:

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)
    }
}

Usalo così:

struct YourView_Previews: PreviewProvider {

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

}

Ciò consente di provare a modificare l'associazione nell'anteprima dal vivo.


Non hai idea di come la tua risposta mi abbia aiutato a produrre codice migliore. Grazie mille. Sto ancora imparando SWIFTUI e BindingProvider che hai scritto è appena al di là delle mie conoscenze rapide limitate. Ho la sensazione di se, ma non capisco al 100%. Grazie comunque.
GrandSteph,

Felice di aiutare! Continuate così e continuate ad imparare: D
Fabian Streitel,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.