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 }

 


참고

ViewBuilder

SwiftUI View: @ViewBuilder

SwiftUI ) ViewBuilder