We have an app that creates controls to set parameters on a component view. We do this with parameter packs, its great and saved us a lot of time when adding new components.
e.g.
struct SandboxView<each Option, Content: View> {
init(
_ options: repeat each Option,
@ViewBuilder content: @escaping (repeat each Option) -> Content
) {
// create controls and the `content` view.
}
}
We just need show a different SandboxView
for each component we have.
(Inside SandboxView
we add SwiftUI controls for each option, e.g. a Picker for enums, a TextField for strings.)
SandboxView(ButtonTheme.Corner.rounded,
"Button Title"
) { corner, title in
ButtonComponent(variant: variant, title: title)
}
Now we want to also show the components on watchOS, we are trying to send the parameters via WatchConnectivity
so sending Codable
encoded data to the watch.
We can send a custom struct for each component, and we can encode and decode our parameter pack!
struct DataWithType: Codable {
let data: Data
let type: SupportedType
}
struct WatchContainerSimple: Codable {
var collection: [DataWithType] = []
init<each Option: Codable>(options: repeat each Option) throws {
for option in repeat each options {
let supportedType: SupportedType
switch type(of: option) {
case is Bool.Type: supportedType = .bool
// more types....
default: throw CodingError.unsupportedType
}
let data = try JSONEncoder().encode(option)
collection.append(DataWithType(data: data, type: supportedType))
}
}
init(from decoder: any Decoder) throws {
var collection: [DataWithType] = []
let codableWithTypes = try decoder.singleValueContainer().decode([DataWithType].self)
for codableWithType in codableWithTypes {
collection.append(DataWithType(data: codableWithType.data, type: codableWithType.type))
}
self.collection = collection
}
}
Is it possible to programmatically instantiate a parameter pack from an array or dictionary? It might be hacky but we can send values to indicate the type we want to use for each type in the pack, but we are not sure how to instantiate it.
In the WWDC video Generalize APIs with parameter packs the host says "The result is a comma-separated list of types..." and obviously arrays can be instantiated with comma separated values but can that array be passed in a way that works with a parameter pack?
Is there a way to create a parameter pack without using the repeat
, each
pattern?