3

If I wanted to create a preview for a SwiftUI view that contains a @Binding I would have previously written something like this:

struct SpecialButton_Preview: PreviewProvider {
    static var previews: some View {
        @State var value: Bool = true
        SpecialButton(isOn: $value)
    }
}

However Xcode 15 now comes with a new syntax (#Preview) but when I try to add my example state property, it does not work:

#Preview {  // Error: Ambiguous use of 'Preview(_:traits:body:)'
    @State var value: Bool = true
    SpecialButton(isOn: $value)
}

How can I make this work?

de.
  • 7,068
  • 3
  • 40
  • 69

4 Answers4

5

You need to return the View to preview. I'm not exactly sure how this works, it has to do with how Swift macros work.

#Preview {
    @State var value: Bool = true
    return SpecialButton(isOn: $value)
}

From the WWDC Slack: "The new #Previews macro simply takes a closure that returns the thing to be previewed. So you can declare local variables or do other setup necessary in there just like you would in any other closure."

  • This gives me the following error: `Cannot use explicit 'return' statement in the body of result builder 'ViewBuilder'` – Ribena Jun 15 '23 at 07:53
  • @Ribena what did your whole code snippet look like? I put this in Xcode 15 beta 1 and it worked (also note this is subject to change because this is a beta Xcode right now) – Mikaela Caron Jun 19 '23 at 20:08
3

This is what I ended up doing in order to have a mutable value:


#Preview {
    struct PreviewWrapper: View {
        @State var value: Bool = true
        
        var body: some View {
            SpecialButton(isOn: $value)
        }
    }
    return PreviewWrapper()
}

de.
  • 7,068
  • 3
  • 40
  • 69
  • What does doing this accomplish? in this case, you could use what is mentioned here: https://stackoverflow.com/a/76468419/17309983 – Mikaela Caron Jun 19 '23 at 20:11
2

What you could do before and still can do is:

SpecialButton(isOn: .constant(true))
ChrisR
  • 9,523
  • 1
  • 8
  • 26
0

Do you need to keep it as a binding var in your preview? Otherwise try this, as it seems to work for me:

#Preview {
    SpecialButton(isOn: true)
}

I'd elaborate on the 'why' but that's still unclear!

Ribena
  • 1,086
  • 1
  • 11
  • 20
  • Yes, the whole point is to preview "a SwiftUI view that contains a @Binding". – de. Jun 15 '23 at 08:21
  • @de. ...which my solution does, in a way? In my seemingly identical case, it allows my View containing a @Binding to be previewed whereas none of the other currently stated solutions work for me. Are you not getting `Cannot use explicit 'return' statement in the body of result builder 'ViewBuilder'` when you try the accepted solution, as I did when I tried it with the code you've provided? – Ribena Jun 15 '23 at 09:22