ViewBuilder helps you create custom containers that can hold many views easily. It makes your code cleaner and more flexible.
ViewBuilder for custom containers in iOS Swift
@ViewBuilder content: () -> some View
The @ViewBuilder attribute allows you to write multiple views inside a closure without wrapping them in a container manually.
It automatically combines the views into a single view group.
struct MyContainer<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
VStack {
content
}
}
}MyContainer {
Text("Hello")
Text("World")
}struct Card<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
content
.padding()
.background(Color.gray.opacity(0.2))
.cornerRadius(10)
}
}This example shows a custom container called MyContainer that uses @ViewBuilder to accept multiple child views. It stacks them vertically with spacing and adds a blue border around them. Inside the container, we put a title, a subtitle, and a button.
import SwiftUI struct MyContainer<Content: View>: View { let content: Content init(@ViewBuilder content: () -> Content) { self.content = content() } var body: some View { VStack(spacing: 10) { content } .padding() .border(Color.blue, width: 2) } } struct ContentView: View { var body: some View { MyContainer { Text("Hello") .font(.title) Text("This is inside a custom container.") .foregroundColor(.gray) Button("Tap me") { print("Button tapped") } .buttonStyle(.borderedProminent) } .padding() } } @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } }
Use @ViewBuilder only on closures that return views.
It helps avoid manually wrapping views in containers like VStack or HStack.
Remember to specify the generic Content: View type when creating custom containers.
ViewBuilder lets you create flexible containers that hold multiple views.
It simplifies writing child views inside closures without extra wrappers.
Custom containers with @ViewBuilder make your UI code cleaner and reusable.
Practice
@ViewBuilder in SwiftUI custom containers?Solution
Step 1: Understand what
@ViewBuilderdoes@ViewBuilderlets you write multiple views inside a closure without needing to wrap them in a container likeVStack.Step 2: Identify the purpose in custom containers
It simplifies building flexible UI containers that can hold many child views easily.Final Answer:
To allow multiple child views inside a closure without extra wrappers -> Option CQuick Check:
@ViewBuilder= multiple child views [OK]
- Thinking it handles animations
- Confusing it with data storage
- Assuming it manages network calls
@ViewBuilder in SwiftUI?Solution
Step 1: Check the correct syntax for
The parameter must be a closure returning@ViewBuilderparametersome Viewand marked with@ViewBuilder.Step 2: Verify the return type and usage
The function returnssome Viewand calls the closure withcontent().Final Answer:
func MyContainer(@ViewBuilder content: () -> some View) -> some View { content() } -> Option AQuick Check:
Correct syntax = func MyContainer(@ViewBuilder content: () -> some View) -> some View { content() } [OK]
- Using View instead of some View
- Missing @ViewBuilder attribute
- Wrong return type in function
struct MyStack: View {
let content: () -> some View
var body: some View {
VStack {
content()
}
}
}
struct ContentView: View {
var body: some View {
MyStack {
Text("Hello")
Text("World")
}
}
}Solution
Step 1: Analyze the content closure type
The content closure returnssome Viewbut is not marked with@ViewBuilder, so it cannot return multiple views.Step 2: Understand the effect on multiple child views
Passing twoTextviews without@ViewBuildercauses a compile-time error because the closure expects a single view.Final Answer:
A compile-time error because multiple views are not allowed -> Option BQuick Check:
Missing @ViewBuilder causes error with multiple views [OK]
- Assuming multiple views work without @ViewBuilder
- Thinking texts concatenate automatically
- Ignoring closure return type rules
struct CustomContainer: View {
let content: () -> some View
var body: some View {
HStack {
content()
}
}
}
// Usage
CustomContainer {
Text("One")
Text("Two")
}Solution
Step 1: Check the content closure declaration
The content closure is declared as() -> some Viewwithout@ViewBuilder, so it cannot accept multiple views.Step 2: Fix by adding
Adding@ViewBuilder@ViewBuilderbefore the content parameter allows multiple child views inside the closure.Final Answer:
Missing @ViewBuilder on content parameter; add @ViewBuilder to fix -> Option DQuick Check:
Use @ViewBuilder to accept multiple views [OK]
- Changing container type instead of fixing closure
- Misunderstanding closure return types
- Trying to convert struct to function unnecessarily
@ViewBuilder to achieve this?Solution
Step 1: Use generic Content type with @ViewBuilder
To accept multiple views, declare a genericContent: Viewand mark theinitparameter with@ViewBuilder.Step 2: Build the body with VStack and add border
WrapcontentinsideVStackand apply.border(Color.red)modifier to the stack.Final Answer:
struct RedBorderStack<Content: View>: View { let content: Content init(@ViewBuilder content: () -> Content) { self.content = content() } var body: some View { VStack { content } .border(Color.red) } } -> Option AQuick Check:
Generic + @ViewBuilder in init + VStack { content } + border [OK]
- Omitting generic Content type
- Not using @ViewBuilder for multiple views
- Placing border on content() instead of VStack
Ready to prove it?
Pass the test and this pattern moves unknown
