I've been using @ViewBuilder
like so:
@ViewBuilder
var warning: some View {
if someWarningIsShown {
Text("WARNING")
}
}
This works fine, but I'm trying to figure out how @ViewBuilder
works when the conditional isn't met. Since the type isn't optional I assume that something other than nil
is returned. EmptyView()
? AnyView(EmptyView())
? What also strikes me is that there's no return keyword by the Text()
. How's that even possible? I'm guessing @ViewBuilder
is operating in an unconventional way. Can anyone explain?
This will simply just return an EmptyView
. This is essentially the same as writing:
@ViewBuilder func warning() -> some View {
if someWarningIsShown {
Text("WARNING")
} else {
EmptyView()
}
}
If you want to write a function that allows you to return, you can simply omit the @ViewBuilder
and return within your code as follows (note that all paths through the function must return a value, and all paths must return the same type of view):
func warning() -> some View {
if someWarningIsShown {
return Text("WARNING")
} else {
return Text("SUCCESS")
}
}
You CAN NOT write a non @ViewBuilder
annotated function, that returns different types. For example, the following will return an error telling you that the function declares an opaque return type, but does not return values with the same underlying types. This is only possible with functions annotated with @ViewBuilder
:
func warning() -> some View {
if someWarningIsShown {
return Text("WARNING")
} else {
return EmptyView()
}
}
Given the above info, we can ascertain that the @ViewBuilder
attribute is doing some work under the hood that will return an EmptyView()
when a block contains no statements that it can process. Digging deeper into the underlying code and the documentation we can see this to be true:
static func buildBlock() -> EmptyView
// Builds an empty view from a block containing no statements.