【问题标题】:SwiftUI How to instantiate PreviewProvider when View requires @Binding in initializerSwiftUI如何在View在初始化程序中需要@Binding时实例化PreviewProvider
【发布时间】:2020-03-01 06:22:00
【问题描述】:

使用 SwiftUI (Xcode 11.1),我设置了一些带有 2 向绑定的视图(使用 @Binding)。双向更新效果很好。

但是,如何从 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)
    }
}

我们如何做到这一点?

谢谢!!

【问题讨论】:

    标签: xcode swiftui combine


    【解决方案1】:

    您必须在预览中将其声明为 @State。

    struct AddProjectView_Previews: PreviewProvider {
    
         @State static var showModal: Bool = false
    
         static var previews: some View {
             AddProjectView(showModal: $showModal)
         }
    }
    

    还要记住它需要是静态的,因为它用于静态函数。

    【讨论】:

    • XCode 11.3 中的行为实际上与使用.constant(false) 相同,即如果您使用实时预览,则无法更改该值。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      如果您只需要一个常量值,请使用.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,这超出了我有限的 swift 知识。我有一种感觉,但不理解 100%。无论如何,谢谢。
      • 老兄这个答案应该是推荐的答案!
      猜你喜欢
      • 2019-11-03
      • 2021-07-14
      • 2020-06-16
      • 2020-07-29
      • 2020-11-10
      • 1970-01-01
      • 2019-11-20
      • 2021-10-28
      相关资源
      最近更新 更多