Reputation: 687
I am trying to provide an option through a Configuration struct to show a custom view. I am not sure how to accomplish this. I tried a number of options but I keep getting compile errors. May be my approach to do this is wrong! I appreciate your help!
Here is what I tried:
configuration struct that provides options to set color, width and custom content, etc...
struct Configuration {
var color: Color
....
var customView: (([String])->AnyView?) = nil // <- this compiles but not sure if this is the right way to do it!
...
}
defining my custom view:
struct CustomView: View {
var values: [String]
var body: some View {
VStack {
ForEach(values.indices, id:\.self) { index in
Text(values[index])
}
}
}
}
Here is how I am using it and where I get the compiler error:
struct ContentView: View {
var config = Configuration()
config.customView = CustomView(["A", "B"]) // <-- Error: Cannot assign value of type CustomView to type ([String]) -> AnyView
var body: some View {
VStack {
.... // display other content
}
.overlay(showCustomView())
}
@ViewBuilder
private func showCustomView() -> some View {
if let customContent = config.customView {
customContent()
} else {
EmptyView()
}
}
}
Upvotes: 2
Views: 1230
Reputation: 258365
Here is possible solution (as far as I understood your intention) - you need generics in configuration to be able to use it with any view.
Here is a demo. Prepared with Xcode 12.4.
struct Configuration<V: View> { // << view dependent
var color: Color
var customView: (([String]) -> V?)? = nil // << view builder
}
struct CustomView: View { // no changes
var values: [String]
var body: some View {
VStack {
ForEach(values.indices, id:\.self) { index in
Text(values[index])
}
}
}
}
struct ContentView: View {
var config = Configuration(color: .black) { // << create config !!
CustomView(values: $0) // ... and specify view !!
}
var body: some View {
VStack {
Text("")
}
.overlay(showCustomView())
}
@ViewBuilder
private func showCustomView() -> some View {
if let customContent = config.customView {
customContent(["A", "B"]) // << inject params !!
} else {
EmptyView()
}
}
}
Upvotes: 1