SwiftUI Comment instancier PreviewProvider lorsque View requiert @Binding dans l'initialiseur

10

Avec SwiftUI (Xcode 11.1), j'ai quelques vues configurées avec des liaisons bidirectionnelles (en utilisant @Binding ). La mise à jour bidirectionnelle fonctionne très bien.

Cependant, comment puis-je instancier la vue à partir de PreviewProvider?

Par exemple:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

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

Je ne peux pas faire cela, car "vrai" n'est pas une liaison:

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

Et je ne peux pas faire cela car "les wrappers de propriétés ne sont pas encore pris en charge sur les propriétés locales ":

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

Comment faisons-nous cela?

Merci!!

drewster
la source

Réponses:

15

.constant est destiné exactement à cela:

/// Crée une liaison avec un immuable 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
la source
Parfait! -- Impressionnant!
Drewster
5

Vous devez le déclarer en tant que @State sur votre aperçu.

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

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

Rappelez-vous également qu'il doit être statique car il est utilisé dans une fonction statique.

LuLuGaGa
la source
1
Le comportement dans XCode 11.3 est en fait identique à l'utilisation .constant(false), c'est-à-dire que si vous utilisez l'aperçu en direct, la valeur ne peut pas être modifiée.
Fabian Streitel
4

Si vous n'avez besoin que d'une valeur constante , utilisez .constant(VALUE):

struct YourView_Previews: PreviewProvider {

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

}

Si vous avez besoin d'une valeur qui peut être modifiée dans l'aperçu en direct , j'aime utiliser cette classe d'assistance:

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

Utilisez-le comme ceci:

struct YourView_Previews: PreviewProvider {

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

}

Cela vous permet de tester la modification de la liaison dans l'aperçu en direct.

Fabian Streitel
la source
Vous ne savez pas comment votre réponse m'a aidé à produire un meilleur code. Mille mercis. J'apprends toujours SWIFTUI et BindingProvider que vous avez écrit dépasse de peu mes connaissances rapides. J'ai une idée de si mais je ne comprends pas à 100%. Merci quand même.
GrandSteph
Heureux de vous aider! Continuez et apprenez: D
Fabian Streitel