Swift – How to use parameter packs throughout a type’s initializer, methods & properties

I’m trying to figure out how to use parameter packs to store and retrieve values in a type. This example is simplified down to show the problem I’m having. This is the code I’m running in a playground:

struct Example<each Thing> {
    var things: (repeat each Thing)
}

let e = Example(things: 1, 2, 3.0, "a") // compile error: "Extra arguments at positions #2, #3, #4 in call"

What is the correct way to call the Example struct’s initializer? I also tried defining the initializer but had problems:

struct Example<each Thing> {
    var things: (repeat each Thing)
    
    init(things: repeat each Thing) {
        self.things = (repeat each things)
    }
}

let e = Example(things: 1, 2, 3.0, "a") // crash: "error: Execution was interrupted, reason: signal SIGABRT."

This actually compiles but crashes in the playground. I’m not sure what to do.

If you’re interested in the actual problem, here’s what I’m trying to do. I want to easily provide mutable bindings to my views for SwiftUI previews (so that the preview is interactive unlike when you pass a .constant(...) binding). I followed the BindingProvider approach which allows for one value at a time, like this:

#Preview {
    BindingProvider(true) { binding in
        SomeToggleView(toggleBinding: binding)
    }
}

It would be nice to pass in multiple values to be bound, like this

#Preview {
    BindingProvider(true, "text") { toggleBinding, textFieldBinding in
        SomeToggleAndTextFieldView(toggleBinding: toggleBinding, textFieldBinding: textFieldBinding)
    }
}

So far I’ve tried something like this, but it’s not compiling and giving very vague errors

struct BindingProvider<each T, Content: View>: View {
    
    @State private var state: (repeat each T)
    private var content: (_ binding: Binding<repeat each T>) -> Content
    
    init(_ initialState: repeat each T, @ViewBuilder content: @escaping (_ binding: Binding<repeat each T>) -> Content) {
        self.content = content
        self._state = State(initialValue: initialState)
    }
    
    var body: some View {
        self.content($state)
    }
}

Any help would be greatly appreciated!

Leave a Comment