SwiftUI Cómo instanciar PreviewProvider cuando View requiere @Binding en el inicializador

10

Con SwiftUI (Xcode 11.1), tengo algunas vistas configuradas con enlaces bidireccionales (usando @Binding ). La actualización bidireccional funciona muy bien.

Sin embargo, ¿cómo puedo instanciar la vista desde el PreviewProvider?

Por ejemplo:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

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

No puedo hacer esto, porque "verdadero" no es un enlace:

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

Y no puedo hacer esto porque " Los envoltorios de propiedades aún no son compatibles con las propiedades locales ":

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

Cómo hacemos esto?

¡¡Gracias!!

Drewster
fuente

Respuestas:

15

.constant está destinado exactamente para eso:

/// Crea un enlace con un inmutable 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
fuente
¡Perfecto! -- ¡Increíble!
Drewster
5

Debe declararlo como @State en su Vista previa.

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

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

También recuerde que debe ser estático, ya que se utiliza en una función estática.

LuLuGaGa
fuente
1
El comportamiento en XCode 11.3 es efectivamente el mismo que usar .constant(false), es decir, si usa la vista previa en vivo, el valor no se puede cambiar.
Fabian Streitel
4

Si solo necesita un valor constante , use .constant(VALUE):

struct YourView_Previews: PreviewProvider {

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

}

Si necesita un valor que se pueda cambiar en la vista previa en vivo , me gusta usar esta clase auxiliar:

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

Úselo así:

struct YourView_Previews: PreviewProvider {

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

}

Esto le permite probar el cambio del enlace en la vista previa en vivo.

Fabian Streitel
fuente
No tienes idea de cómo tu respuesta me ayudó a producir un mejor código. Un millón de gracias. Todavía estoy aprendiendo SWIFTUI y BindingProvider que escribiste está más allá de mi limitado conocimiento rápido. Tengo la sensación de si pero no entiendo al 100%. Gracias de cualquier manera.
GrandSteph
¡Encantado de ayudar! Sigue así y sigue aprendiendo: D
Fabian Streitel