ViewBuilder
is a function builder.
ViewBuilder
-based closure content
may produce any kind of views. If there are two or more subviews, it produces a TupleView
:
HStack {
Text("a")
Text("b")
}
If there are no subviews, it produces an EmptyView
:
HStack {
}
The best place to read about function builders is the original proposal. But there are also many articles about function builders including this answer on stackoverflow.com.
The implementation of ViewBuilder
looks like this:
@_functionBuilder
public struct ViewBuilder {
@_alwaysEmitIntoClient
public static func buildBlock() -> EmptyView {
.init()
}
@_alwaysEmitIntoClient
public static func buildBlock<Content>(_ content: Content) -> Content where Content: View {
content
}
@_alwaysEmitIntoClient
public static func buildIf<Content>( _ content: Content?) -> Content? where Content: View {
content
}
@_alwaysEmitIntoClient
public static func buildEither<TrueContent, FalseContent>(
first: TrueContent) -> _ConditionalContent<TrueContent, FalseContent>
where TrueContent: View, FalseContent: View
{
.init(storage: .trueContent(first))
}
@_alwaysEmitIntoClient
public static func buildEither<TrueContent, FalseContent>(
second: FalseContent) -> _ConditionalContent<TrueContent, FalseContent>
where TrueContent: View, FalseContent: View
{
.init(storage: .falseContent(second))
}
@_alwaysEmitIntoClient
public static func buildBlock<C0, C1>(
_ c0: C0,
_ c1: C1) -> TupleView<(C0, C1)>
where C0: View, C1: View
{
.init((c0, c1))
}
@_alwaysEmitIntoClient
public static func buildBlock<C0, C1, C2>(
_ c0: C0,
_ c1: C1,
_ c2: C2) -> TupleView<(C0, C1, C2)>
where C0: View, C1: View, C2: View
{
.init((c0, c1, c2))
}
// ...
}