In SwiftUI, @ViewBuilder is a special attribute used to build views. It is a result builder that allows you to construct views in a more declarative and readable manner. @ViewBuilder can be used to build complex view hierarchies by composing multiple views together within a single closure.
The @ViewBuilder attribute can be very useful when creating custom views that need to accept multiple child views, making the code more concise and readable. It is automatically used in many SwiftUI container views like VStack, HStack, ZStack, and ForEach.
Although the body property itself doesn’t require @ViewBuilder, the compiler automatically applies @ViewBuilder to it, allowing you to write multiple views inside the body without explicitly using a container view.
public protocol View {
associatedtype Body : View
@ViewBuilder var body: Self.Body { get }
}You can use @ViewBuilder in different contexts, such as custom view initializers, methods, and computed properties, to enable the same declarative syntax used in SwiftUI’s built-in container views.
Using @ViewBuilder with initializers allows the creation of views with complex hierarchies directly in the initializer, enabling the passing of multiple child views.
Here’s another example with a custom view initializer:
import SwiftUI
struct CustomContainer<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
VStack {
content
}
}
}
struct ContentView: View {
var body: some View {
CustomContainer {
Text("This is inside the custom container")
Text("Another view inside the custom container")
}
}
}In this case, CustomContainer uses the @ViewBuilder attribute in its initializer to accept multiple views, allowing you to pass in multiple views when creating an instance of CustomContainer.
Using @ViewBuilder with methods encapsulates view-building logic within methods, making it easier to reuse and maintain. Methods can accept parameters, suitable for dynamic or parameterized view generation, allowing the same method to be used with different inputs to produce different views.
Here’s a basic example to illustrate the usage of @ViewBuilder in methods:
import SwiftUI
struct CustomView: View {
var body: some View {
VStack {
content()
}
}
@ViewBuilder
private func content() -> some View {
Text("Hello from CustomView")
Text("This is another piece of text")
}
}In this example VStack is a container that arranges its children in a vertical stack. @ViewBuilder is applied to the content function, allowing it to return multiple Text views without wrapping them explicitly in a container like Group.
Using @ViewBuilder with computed properties can be a powerful way to modularize and reuse parts of your SwiftUI views. Suitable for defining view sections that do not require parameters and can be reused within the same view or other views.
struct ContentView: View {
var body: some View {
VStack {
header
bodyContent
footer
}
}
@ViewBuilder
var header: some View {
Text("Header")
.font(.largeTitle)
.padding()
Divider()
}
@ViewBuilder
var bodyContent: some View {
Text("This is the main content area.")
.padding()
Text("You can add more views here.")
.padding()
}
@ViewBuilder
var footer: some View {
Divider()
Text("Footer")
.font(.footnote)
.padding()
}
}