Curiosity
Curiosity

Reputation: 264

How do you preview a view containing a binding to its parent view's state?

I present this view as a sheet from its parent view

struct NamesView: View {
    @Binding var match: Match

    var body: some View {
        ...
    }
}

Since the match source of truth is in the parent view presenting this NamesView sheet, when the view is constructed I pass in a $match binding and data flows as intended.

However, when constructing this view in a preview provider

struct NamesView_Previews: PreviewProvider {
    static var previews: some View {
        NamesView()
    }
}

the compiler says that NamesView() expects a match argument of type Binding<Match> (Match being the parent view presenting this view as a sheet). I'm not sure what would be a good way to proceed from here or if this is a limitation of SwiftUI.

Upvotes: 3

Views: 630

Answers (3)

Michael Long
Michael Long

Reputation: 1102

I wrote about this in depth here, but the short version is simply to add the following extension:

extension Binding {
    public static func variable(_ value: Value) -> Binding<Value> {
        var state = value
        return Binding<Value> {
            state
        } set: {
            state = $0
        }
    }
}

And then do...

struct NamesView_Previews : PreviewProvider {
    static var previews: some View {
        NamesView(match: .variable(Match()))
    }
}

This lets you actually mutate the value, useful when doing live previews in Xcode 14.

Upvotes: 0

Chris
Chris

Reputation: 8126

Try this:

struct NamesView_Previews: PreviewProvider {
        static var previews: some View {
            NamesView(match:.constant(Match()))
        }
    }

Upvotes: 0

Asperi
Asperi

Reputation: 258601

If you want only constant preview, then it can be

struct NamesView_Previews: PreviewProvider {
        static var previews: some View {
            NamesView(match: .constant(Match()))
        }
    }

if you want it in live, the it can be

struct NamesView_Previews: PreviewProvider {
    struct BindingTestHolder: View {
        @State private var testedMatch = Match()
        var body: some View {
            NamesView(match: $testedMatch)
        }
    }

    static var previews: some View {
        BindingTestHolder()
    }
}

Upvotes: 7

Related Questions