SwiftUI @Binding Initialize

IosSwiftSwiftuiIos13

Ios Problem Overview


Been playing around with SwiftUI and understood the concept of BindableObjects etc so far (at least I hope I do).

I bumped into a stupid problem I can't seem to find an answer for: How do you initialize a @Binding variable?

I have the following code:

struct LoggedInView : View {

    @Binding var dismissView: Bool

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

In my preview code, I want to pass that parameter of type Binding<Bool>:

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

How would I go an initialize it? tried:

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

Or even:

@Binding var dismissView: Bool = false

But none worked... any ideas?

Ios Solutions


Solution 1 - Ios

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

Solution 2 - Ios

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

Solution 3 - Ios

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

Solution 4 - Ios

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

Solution 5 - Ios

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDonBaronView Question on Stackoverflow
Solution 1 - IosPaulw11View Answer on Stackoverflow
Solution 2 - IosNeverwinterMoonView Answer on Stackoverflow
Solution 3 - IosatalayasaView Answer on Stackoverflow
Solution 4 - IosMasterMindView Answer on Stackoverflow
Solution 5 - IosAndrew BogaevskyiView Answer on Stackoverflow