마틴 말했듯이 당신에 대한 설명서를 보면, VStack
의 init(alignment:spacing:content:)
, 당신은 것을 볼 수 있습니다 content:
매개 변수는 속성이 있습니다 @ViewBuilder
:
init(alignment: HorizontalAlignment = .center, spacing: Length? = nil,
@ViewBuilder content: () -> Content)
이 속성은 ViewBuilder
생성 된 인터페이스를 보면 다음과 같은 유형을 참조합니다 .
@_functionBuilder public struct ViewBuilder {
public static func buildBlock() -> EmptyView
public static func buildBlock(_ content: Content) -> Content
where Content : View
}
이 @_functionBuilder
속성은 " 함수 빌더 " 라는 비공식적 기능의 일부로 , 여기에서 Swift의 진화에 대해 언급했으며 Xcode 11과 함께 제공되는 Swift 버전을 위해 특별히 구현되어 SwiftUI에서 사용할 수 있습니다.
유형을 표시하면 @_functionBuilder
함수, 계산 된 속성 및이 경우 함수 유형의 매개 변수와 같은 다양한 선언에서 사용자 정의 속성으로 사용할 수 있습니다. 이러한 주석이 달린 선언은 함수 빌더를 사용하여 코드 블록을 변환합니다.
- 주석이 달린 함수의 경우 변환되는 코드 블록이 구현입니다.
- 주석이 달린 계산 된 속성의 경우 변환되는 코드 블록이 게터입니다.
- 함수 유형의 주석이 달린 매개 변수의 경우 변환되는 코드 블록은 전달되는 클로저 표현식입니다 (있는 경우).
함수 빌더가 코드를 변환하는 방식은 일련의 표현식을 가져와 단일 값으로 통합하는와 같은 빌더 메소드 의 구현에 의해 정의됩니다 buildBlock
.
예를 들어 1 ~ 10 개의 준수 매개 변수 를 ViewBuilder
구현 buildBlock
하여 View
여러 뷰를 단일으로 통합합니다 TupleView
.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ViewBuilder {
public static func buildBlock<Content>(_ content: Content)
-> Content where Content : View
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1)
-> TupleView<(C0, C1)> where C0 : View, C1 : View
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2)
-> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View
}
이를 통해 VStack
의 이니셜 라이저에 전달 된 클로저 내의 뷰 표현식 세트를 buildBlock
동일한 수의 인수 를 사용하는 호출로 변환 할 수 있습니다 . 예를 들면 :
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World")
Text("Hello World!")
}
}
}
에 대한 호출로 변환됩니다 buildBlock(_:_:)
.
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
ViewBuilder.buildBlock(Text("Hello, World"), Text("Hello World!"))
}
}
}
결과 은폐하는 결과 유형 some View
에 의해 충족되고 TupleView<(Text, Text)>
.
당신은 점에 유의하겠습니다 ViewBuilder
만 정의 buildBlock
우리가 11 파단을 정의하려고 시도 그렇다면, 10 개의 매개 변수를 :
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
}
}
이 코드 블록을 처리 할 빌더 메서드가 없기 때문에 컴파일러 오류가 발생합니다 (이 기능은 아직 작업 중이므로 관련 오류 메시지는 그다지 도움이되지 않습니다).
실제로는 사람들이이 제한에 자주 부딪 힐 것이라고 생각하지 않습니다. 예를 들어 위의 예는 ForEach
대신 뷰를 사용하여 더 잘 제공 됩니다.
var body: some View {
VStack(alignment: .leading) {
ForEach(0 ..< 20) { i in
Text("Hello world \(i)")
}
}
}
그러나 정적으로 정의 된 뷰가 10 개 이상 필요한 경우 뷰를 사용하여이 제한을 쉽게 해결할 수 있습니다 Group
.
var body: some View {
VStack(alignment: .leading) {
Group {
Text("Hello world")
}
Group {
Text("Hello world")
}
}
ViewBuilder
또한 다음과 같은 다른 함수 작성기 메서드를 구현합니다.
extension ViewBuilder {
public static func buildEither<TrueContent, FalseContent>(first: TrueContent)
-> ConditionalContent<TrueContent, FalseContent>
where TrueContent : View, FalseContent : View
public static func buildEither<TrueContent, FalseContent>(second: FalseContent)
-> ConditionalContent<TrueContent, FalseContent>
where TrueContent : View, FalseContent : View
}
이를 통해 if 문을 처리 할 수 있습니다.
var body: some View {
VStack(alignment: .leading) {
if .random() {
Text("Hello World!")
} else {
Text("Goodbye World!")
}
Text("Something else")
}
}
다음으로 변환됩니다.
var body: some View {
VStack(alignment: .leading) {
ViewBuilder.buildBlock(
.random() ? ViewBuilder.buildEither(first: Text("Hello World!"))
: ViewBuilder.buildEither(second: Text("Goodbye World!")),
Text("Something else")
)
}
}
( ViewBuilder.buildBlock
명확성 을 위해 중복 1 인수 호출을 냄).
@ViewBuilder
developer.apple.com/documentation/swiftui/viewbuilder 가 있음을 보여줍니다 .