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

但是都没用,有什么想法吗?

40652 次浏览
  • If you need a simple property that belongs to a single view you should use @State
  • If you need to have complex property that may belong to several view(like 2-3 views) you shall use @ObjectBinding
  • Lastly, if you need to have property that needs to use all around views you shall use @EnvironmentObject. Source for detail information

For your case, if you still would like to initialize your Binding variable you can use:

var binding: Binding = .constant(false)

When you use your LoggedInView in your app you do need to provide some binding, such as an @State from a previous view or an @EnvironmentObject.

For the special case of the PreviewProvider where you just need a fixed value you can use .constant(false)

E.g.

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

Using Binding.constant(false) is fine but only for static previews. If you actually wanna launch a Live Preview, constant will not behave the same way as the real case as it will never be updated by your actions. I personally use Live Preview a lot, as I can play around with an isolated view.

Here is what I do for previews requiring 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)
}
}
}

I'm using different configurations of my view within one preview (I'm working on a custom control and want to see a different configuration of it). I've extended the implementation provided by @NeverwinterMoon in order to create multiple independent instances of a view.

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

In preview you have to use .constant(Bool(false)):

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

if you have an object like viewModel you can also use .constant()

struct View_Previews: PreviewProvider {
static var previews: some View {
View(vm:.constant(ViewModel(text: "Sample Text")))
}
}