관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] @ViewBuilder 기능 본문

iOS 응용 (SwiftUI)

[iOS - SwiftUI] @ViewBuilder 기능

jake-kim 2024. 9. 11. 01:36

@ViewBuilder 기능 알아보기

@ViewBuilder
var myView: some View {
    Text("ex")
}
  • @ViewBuilder는 @resultBuilder 기능처럼 return키워드와 콤마를 안쓰고 심플하게 반환할 수 있음
// resultBuilder를 사용한 경우 - 콤마 존재 x
@PersonBuilder
func getPerson() -> [Person] {
  Person(name: "jake", age: 20) // return 키워드를 사용하지 않아도 동작
  Person(name: "kim", age: 22)
  Person(name: "paul", age: 32)
}
  • 하지만 @ViewBuilder를 단순히 @resultBuilder로 만든 것으로 오해할 수 있는데 다른 기능도 존재

@ViewBuilder 중요한 기능

  • 1) 위에서 알아본 콤마, return 생략
@ViewBuilder
var myView: some View {
    Text("ex")
}
  • 2) resultBuilder의 기능과 동일하게 여러가지 뷰를 개행으로 구분하여 한꺼번에 제공 가능
// @ViewBuilder를 안쓰면 에러 발생
// error: Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
var myView: some View {
    VStack {
        Text("123")
    }
    if toggle {
        Text("toggle is true")
    } else {
        Text("toggle is false")
    }
}
  • 3) @ViewBuilder를 사용하지 않으면 여러가지 유형의 뷰 리턴 불가
// Fail
var myView3: some View {
    if Bool.random() {
        Text("a") // error: Branches have mismatching types 'Text' and 'EmptyView'
    } else {
        EmptyView()
    }
}

// OK
@ViewBuilder
var myView3: some View {
    if Bool.random() {
        Text("a")
    } else {
        EmptyView()
    }
}
  • 4) 기타 기능
    • 가끔 some View 유형을 리턴해야하지만 조건에 따라서 어떤 뷰도 안쓰고 싶을때 EmptyView를 리턴해야하는 상황이 있는데, AnyView로 감싸라고 뜰 때, @ViewBuilder를 붙이면 감싸지 않고 EmptyView바로 사용 가능
    • if, else과 같은 조건문이 있을 때 @ViewBuilder를 안쓰면 조건에 따라 뷰가 변경되지 않는 버그가 존재
    @ViewBuilder
    var someView: some View {
        if viewModel.isShowSomeView {
            VStack {
                Spacer(minLength: 32)
                HStack {
                    AView()
                }
            }
        } else {
            EmptyView() // AnyView(EmptyView())
        }
    }

정리

  • @ViewBuilder를 사용하면 뷰를 여러가지 return 키워드 없이 선언형으로 작성이 가능
  • 따로 프로퍼티나 함수로 뷰를 관리할 땐 @ViewBuilder를 붙여서 관리하는게 용이
    • Swift내장된 View 프로토콜도 역시, body프로퍼티가 @ViewBuilder를 따르고 있음
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol View {
    @ViewBuilder @MainActor var body: Self.Body { get }
}
Comments