Swift
SwiftUI: ViewBuilder
songmoro
2023. 10. 18. 21:09
ViewBuilder: A custom parameter attribute that constructs views from closures.(클로저에서 뷰를 구성하는 사용자 지정 매개 변수 속성.)
@resultBuilder
struct ViewBuilder
ViewBuilder는 클로저를 통해 뷰를 구성할 수 있게 해 줍니다.
매개 변수를 사용해 하나 이상의 다양한 자식 뷰를 제공하기 위해 사용해요.
사용 예 1

struct ContentView: View {
var body: some View {
VStack {
HStack {
Image(systemName: "1.lane")
Text("1번 텍스트")
Image(systemName: "text.bubble")
}
.foregroundColor(.black)
HStack {
Image(systemName: "2.lane")
Text("2번 텍스트")
Image(systemName: "text.bubble.fill")
}
.foregroundColor(.blue)
HStack {
Image(systemName: "3.lane")
Text("3번 텍스트")
Image(systemName: "text.bubble.rtl")
Image(systemName: "text.bubble.rtl")
}
.foregroundColor(.brown)
}
}
}
위 코드는 인자만 다르고 그 외에는 반복되는 코드입니다.
ViewBuilder를 사용해서 사용자 정의 컨테이너를 만들 수 있습니다.
struct CustomLabel<Content: View>: View {
let color: Color
let number: Int
@ViewBuilder let content: Content
var body: some View {
HStack {
Image(systemName: "\\(number).lane")
Text("\\(number)번 텍스트")
content
}
.foregroundColor(color)
}
}
struct ContentView: View {
var body: some View {
VStack {
CustomLabel(color: .black, number: 1) {
Image(systemName: "text.bubble")
}
CustomLabel(color: .blue, number: 2) {
Image(systemName: "text.bubble.fill")
}
CustomLabel(color: .brown, number: 3) {
Image(systemName: "text.bubble.rtl")
Image(systemName: "text.bubble.rtl")
}
}
}
}
사용 예 2

struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe.desk.fill")
.foregroundColor(.black)
Image(systemName: "globe.desk.fill")
.foregroundColor(.black)
Image(systemName: "globe.desk.fill")
.foregroundColor(.black)
Image(systemName: "globe.desk.fill")
.foregroundColor(.blue)
Image(systemName: "globe.desk.fill")
.foregroundColor(.blue)
Image(systemName: "globe.desk.fill")
.foregroundColor(.blue)
Image(systemName: "globe.desk.fill")
.foregroundColor(.brown)
Image(systemName: "globe.desk.fill")
.foregroundColor(.brown)
Image(systemName: "globe.desk.fill")
.foregroundColor(.brown)
}
}
}
가독성을 위해 따로 body에서 코드를 computed property, method로 분리하고자 할 때 쓸 수 있습니다.
struct ContentView: View {
var body: some View {
VStack {
CustomLabel
.foregroundColor(.black)
CustomLabel
.foregroundColor(.blue)
CustomLabel2()
.foregroundColor(.brown)
}
}
@ViewBuilder
var CustomLabel: some View {
Image(systemName: "globe.desk.fill")
Image(systemName: "globe.desk.fill")
Image(systemName: "globe.desk.fill")
}
@ViewBuilder
func CustomLabel2() -> some View {
Image(systemName: "globe.desk.fill")
Image(systemName: "globe.desk.fill")
Image(systemName: "globe.desk.fill")
}
}
추가
body는 암시적으로 ViewBuilder를 채택하고 있기 때문에 별도로 ViewBuilder를 선언하지 않아도 클로저 내부에서 복수의 View를 선언할 수 있습니다.
@ViewBuilder @MainActor var body: Self.Body { get }