Reputation: 2738
I have a generic view with an optional @ViewBuilder
.
I want to have two initializers, one is responsible for setting the @ViewBuilder
and another which should serve as an empty default.
struct OptionalViewBuilder<Content: View>: View {
let content: (() -> Content)?
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
init() {
self.content = nil
}
var body: some View {
VStack {
Text("Headline")
Divider()
content?()
}
}
}
If I initialize the view with the ViewBuilder parameter, it works of course. However, when I use the empty initializer, I get the error message:
Generic parameter 'Content' could not be inferred
struct ContentView: View {
var body: some View {
OptionalViewBuilder {
Text("Text1")
Text("Text2")
}
OptionalViewBuilder() // <-- Generic parameter 'Content' could not be inferred
}
}
I know that Swift needs explicit types at runtime, but is there a way to make the default initializer work anyway?
Upvotes: 5
Views: 2168
Reputation: 2881
You also can pass EmptyView() as default parameter
struct OptionalViewBuilder<Content: View>: View {
let content: () -> Content?
init(@ViewBuilder content: @escaping () -> Content? = { EmptyView() }) {
self.content = content
}
}
Upvotes: -1
Reputation: 49590
Because OptionalViewBuilder
is generic with respect to its Content
type, you'd need to define that type as something in your default case. This could be EmptyView
, if you don't want to render anything.
To do that, you'd need an init
which is constrained to Content == EmptyView
, and the content
property need not be optional:
struct OptionalViewBuilder<Content: View>: View {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
init() where Content == EmptyView {
self.init(content: { EmptyView() })
}
var body: some View {
VStack {
Text("Headline")
Divider()
content()
}
}
}
Upvotes: 7
Reputation: 606
I can make the compile error go away by adding an empty closure, like this:
struct ContentView: View {
var body: some View {
OptionalViewBuilder {
Text("Text1")
Text("Text2")
}
OptionalViewBuilder() {} // I added an empty closure
}
}
Does this get you what you need?
Upvotes: 1