SwiftUIイニシャライザでビューが@Bindingを必要とするときにPreviewProviderをインスタンス化する方法


10

SwiftUI(Xcode 11.1)を使用すると、(@ Bindingを使用して)2方向バインディングを設定したビューがいくつかあります。双方向の更新はうまくいきます。

ただし、PreviewProviderからビューをインスタンス化するにはどうすればよいですか?

例えば:

struct AddProjectView: View {

    @Binding public var showModal: Bool

    var body: some View {

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

「true」はバインディングではないため、これを行うことはできません。

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

ローカルプロパティでプロパティラッパーがまだサポートされていない」ため、これを行うことはできません。

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

これどうやってやるの?

ありがとう!!

回答:


15

.constant それはまさにそのためのものです:

///不変でバインディングを作成します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))
    }
}

パーフェクト! - 驚くばかり!
ドリュースター

5

プレビューで@Stateとして宣言する必要があります。

struct AddProjectView_Previews: PreviewProvider {

     @State static var showModal: Bool = false

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

また、静的関数で使用されるため、静的である必要があることにも注意してください。


1
XCode 11.3の動作は、実質的に.constant(false)を使用する場合と同じです。つまり、ライブプレビューを使用する場合、値は変更できません。
Fabian Streitel

4

定数値のみが必要な場合は、次を使用します.constant(VALUE)

struct YourView_Previews: PreviewProvider {

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

}

ライブプレビュー変更できる値が必要な場合は、このヘルパークラスを使用します。

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

次のように使用します。

struct YourView_Previews: PreviewProvider {

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

}

これにより、ライブプレビューでバインディングの変更をテストできます。


あなたはあなたの答えが私がより良いコードを生成するのにどのように役立ったかを知りません。どうもありがとう。私はまだSWIFTUIを学習しています。あなたが書いたBindingProviderは、私の限られた迅速な知識を超えています。もしかしたら100%理解できないかもしれません。とにかくありがとう。
GrandSteph

助けてくれてうれしい!継続して学習を続ける:D
Fabian Streitel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.