SwiftUI @Binding 初始化

SwiftUI @Binding Initialize

一直在玩弄 SwiftUI 并理解 BindableObjects 等的概念(至少我希望我能理解)。

我遇到了一个我似乎找不到答案的愚蠢问题: 如何初始化 @Binding 变量?

我有以下代码:

struct LoggedInView : View {

    @Binding var dismissView: Bool

    var body: some View {
        VStack {
            Text("Hello World")
        }
    }
}

在我的预览代码中,我想传递 Binding<Bool>:

类型的参数
#if DEBUG
struct LoggedInView_Previews : PreviewProvider {
    static var previews: some View {
        LoggedInView(dismissView: **Binding<Bool>**)
    }
}
#endif

我该如何初始化它?尝试过:

Binding<Bool>.init(false)
Binding<Bool>(false)

甚至:

@Binding var dismissView: Bool = false

但是 none 有效...有什么想法吗?

  • 如果您需要一个属于单一视图的简单 属性 应该使用 @State
  • 如果你需要复杂的 属性 那可能 属于您应使用的多个视图(如 2-3 个视图) @ObjectBinding
  • 最后,如果您需要 属性 需要使用全方位视图,您应该使用 @EnvironmentObject。 来源 for detail information

对于您的情况,如果您仍想初始化 Binding 变量,您可以使用:

var binding: Binding = .constant(false)

当您在应用中使用 LoggedInView 时,您确实需要提供一些绑定,例如来自先前视图的 @State@EnvironmentObject

对于 PreviewProvider 的特殊情况,您只需要一个固定值,您可以使用 .constant(false)

例如

#if DEBUG
struct LoggedInView_Previews : PreviewProvider {
    static var previews: some View {
        LoggedInView(dismissView: .constant(false))
    }
}
#endif

使用 Binding.constant(false) 很好,但仅适用于静态预览。如果您真的想启动实时预览,constant 的行为方式将与实际情况不同,因为它永远不会被您的操作更新。我个人经常使用实时预览,因为我可以玩孤立的视图。

这是我对需要 Binding 的预览所做的:

import SwiftUI

struct SomeView: View {
   @Binding var code: String

   var body: some View {
     // some views modifying code binding
   }
}

struct SomeView_Previews: PreviewProvider {
  static var previews: some View {
    PreviewWrapper()
  }

  struct PreviewWrapper: View {
    @State(initialValue: "") var code: String

    var body: some View {
      SomeView(code: $code)
    }
  }
}

我在一个预览中使用了我的视图的不同配置(我正在处理自定义控件并希望看到它的不同配置)。我扩展了@NeverwinterMoon 提供的实现,以便创建多个独立的视图实例。

struct SomeView: View {
   @Binding var value: Int

   var body: some View {
     // some views modifying code binding
   }
}

struct SomeView_Previews: PreviewProvider {
  static var previews: some View {
    VStack {
      // The same view but with different configurations

      // Configuration #1
      PreviewWrapper() { value in
        SomeView(value: value)
          .background(Color.blue)
      }

      // Configuration #2      
      PreviewWrapper(initialValue: 2) { value in
        SomeView(value: value)
          .padding()
      }
    }
  }

  struct PreviewWrapper<Content: View>: View {
    @State var value: Int
    private let content: (Binding<Int>) -> Content
    
    init(
      initialValue: Int = 0,
      @ViewBuilder content: @escaping (Binding<Int>) -> Content
    ) {
      self.value = initialValue
      self.content = content
    }
    
    var body: some View {
      content($value)
    }
  }
}

在预览中你必须使用 .constant(Bool(false)):

#if DEBUG
struct LoggedInView_Previews : PreviewProvider {
    static var previews: some View {
        LoggedInView(dismissView: .constant(Bool(false))
    }
}
#endif