SwiftUI Como instanciar o PreviewProvider quando o View requer @Binding no inicializador

10

Com o SwiftUI (Xcode 11.1), eu tenho algumas Views configuradas com ligações bidirecionais (usando @Binding ). A atualização bidirecional funciona muito bem.

No entanto, como posso instanciar a exibição do PreviewProvider?

Por exemplo:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

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

Não posso fazer isso, porque "true" não é uma ligação:

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

E não posso fazer isso porque " Os invólucros de propriedades ainda não são suportados nas propriedades locais ":

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

Como vamos fazer isso?

Obrigado!!

drewster
fonte

Respostas:

15

.constant é exatamente para isso:

/// Cria uma ligação com um imutável 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
fonte
Perfeito! -- Impressionante!
Drewster 5/11
5

Você deve declará-lo como @State na sua visualização.

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

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

Lembre-se também de que ele precisa ser estático, pois é usado em uma função estática.

LuLuGaGa
fonte
11
O comportamento no XCode 11.3 é efetivamente o mesmo que o uso .constant(false), ou seja, se você usar a visualização ao vivo, o valor não poderá ser alterado.
Fabian Streitel
4

Se você precisar apenas de um valor constante , use .constant(VALUE):

struct YourView_Previews: PreviewProvider {

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

}

Se você precisar de um valor que possa ser alterado na visualização ao vivo , eu gosto de usar esta classe 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)
    }
}

Use-o assim:

struct YourView_Previews: PreviewProvider {

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

}

Isso permite testar a alteração da encadernação na visualização ao vivo.

Fabian Streitel
fonte
Você não tem ideia de como sua resposta me ajudou a produzir um código melhor. Graças um milhão. Ainda estou aprendendo SWIFTUI e BindingProvider que você escreveu está além do meu conhecimento rápido e limitado. Tenho uma sensação de que, mas não entendo 100%. Obrigado de qualquer maneira.
GrandSteph
Feliz em ajudar! Continue assim e continue aprendendo: D
Fabian Streitel