Write a custom container view that takes a result-builder @ViewBuilder closure
Write a reusable CardView container that wraps any content the caller supplies in a styled card (padding, background, rounded corners).
Requirements:
- The caller passes its children as a trailing closure, e.g.
CardView { Text("Hi"); Image(...) }. - Accept several child views without wrapping them in an array or
AnyView.
struct CardView<Content: View>: View {
// store the content and add a @ViewBuilder initializer
var body: some View {
// wrap the content in a styled container
}
}
Write the implementation.
Make a generic struct storing content: Content (Content: View) and mark its init closure @ViewBuilder content: () -> Content. Store the result and place content in your layout. The attribute lets callers pass several views as one closure.
- ✗Typing the closure as
[AnyView]instead of a generic@ViewBuilderclosure - ✗Forgetting
@ViewBuilder, so only a single child view compiles - ✗Making the content closure
@escapingand re-invoking it per render
- →Why does
@ViewBuilderlet the caller pass several views without commas or an array? - →What concrete type does the builder produce for multiple children?
A generic content parameter plus a @ViewBuilder initializer is all it takes:
struct CardView<Content: View>: View {
private let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content() // build once, store the result
}
var body: some View {
VStack(alignment: .leading, spacing: 12) {
content
}
.padding()
.background(.regularMaterial)
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
// Usage — several children, one trailing closure, no array, no AnyView:
CardView {
Text("Title").font(.headline)
Text("Subtitle").foregroundStyle(.secondary)
}
@ViewBuilder on the initializer parameter is what turns the { ... } block of several views into a single Content value (a TupleView for multiple children). The closure is called once in init and its result stored, so content is a plain child of the layout — no AnyView, no per-render rebuild.