SwiftUI는 "opaque return type"이라고 하는 Swift의 강력한 기능에 크게 의존합니다. 이 기능은 View를 작성할 때마다 실제로 볼 수 있습니다. 이것은 "View 프로토콜을 준수하는 하나의 개체이지만 무엇을 말하고 싶지는 않습니다."를 의미합니다.
some view를 반환하는 것은 어떤 view type이 되돌아가는지 모르지만 컴파일러는 알고 있음을 의미합니다. 사소해보이지만 중요한 의미가 있습니다.
첫째, some view를 사용하는 것은 성능에 중요합니다. SwiftUI는 사용자 인터페이스를 올바르게 업데이트할 수 있도록 우리가 표시하는 보기를 보고 변경 방법을 이해할 수 있어야 합니다. SwiftUI에 이 추가 정보가 없다면, SwiftUI가 정확히 무엇이 변경되었는지 파악하는 것은 정말 느릴 것입니다. 거의 모든 것을 버리고 모든 작은 변경 후에 다시 시작해야 할 것입니다.
두 번째 차이점은 SwiftUI가 ModifiedContent를 사용하여 데이터를 구축하는 방식 때문에 중요합니다. 이전에 다음 코드를 보여 드렸습니다.
Button("Hello World") {
print(type(of: self.body))
}
.frame(width: 200, height: 200)
.background(.red)
그러면 간단한 버튼이 생성되고 정확한 Swift 유형이 인쇄되고 몇 가지 ModifiedContent 인스턴스가 포함된 긴 출력이 제공됩니다.
View 프로토콜에는 연결된 유형이 있습니다. 이는 Swift가 말하는 View 자체는 아무 의미가 없습니다. View 프로토콜이 어떤 종류의 뷰인지 정확하게 말해야 합니다. Swift가 "이 변수는 배열입니다"라고 말하지 않고 대신 배열에 있는 내용을 "이 변수는 문자열 배열입니다."라고 말하도록 요구하는 것과 유사한 방식으로 구멍이 있습니다.
따라서 다음과 같은 뷰를 작성하는 것은 허용되지 않습니다.
struct ContentView: View {
var body: View {
Text("Hello World")
}
}
이건 가능
struct ContentView: View {
var body: Text {
Text("Hello World")
}
}
뷰를 반환하는 것은 의미가 없습니다. 왜냐하면 Swift는 뷰 내부에 무엇이 있는지 알고 싶어하기 때문입니다. 뷰에는 채워야 하는 큰 구멍이 있습니다. 반면에 Text를 반환하는 것은 괜찮습니다. 왜냐하면 우리가 구멍을 채웠기 때문입니다. Swift는 뷰가 무엇인지 알고 있습니다.
이제 이전 코드로 돌아가 보겠습니다.
Button("Hello World") {
print(type(of: self.body))
}
.frame(width: 200, height: 200)
.background(.red)
우리 body property에서 그 중 하나를 반환하려면 무엇을 작성해야합니까? 사용할 ModifiedContent 구조체의 정확한 조합을 알아내려고 시도할 수 있지만, 그것은 끔찍할 정도로 고통스럽고 단순한 사실은 그것이 모두 내부 SwiftUI 항목이기 때문에 신경 쓰지 않는다는 것입니다.
some view에서 "이것은 버튼이나 텍스트와 같은 view가 될 것이지만 무엇을 말하고 싶지는 않습니다."라고 말할 수 있습니다. 따라서 View에 있는 구멍은 실제 뷰 객체로 채워지지만 정확한 long type을 작성할 필요는 없습니다.
조금 더 복잡해지는 두 곳이 있습니다.
첫 번째 질문에 먼저 답하기 위해 내부에 두 개의 텍스트 뷰가 있는 VStack을 생성하면 SwiftUI는 두 개의 뷰를 포함하는 TupleView를 자동으로 생성합니다. 이는 내부에 정확히 두 개의 뷰를 보유하는 특수한 유형의 뷰입니다. 그래서 VStack은 "이게 어떤 뷰인가요?"를 채웁니다. "두 개의 텍스트 보기가 포함된 TupleView입니다."
그리고 VStack 내부에 3개의 텍스트 보기가 있다면 어떻게 될까요? 그런 다음 세 가지 보기를 포함하는 TupleView입니다. 또는 4개의 보기. 또는 8개의 보기 또는 10개의 보기 - 말 그대로 10가지 다른 종류의 콘텐츠를 추적하는 TupleView 버전이 있습니다.
TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)>
이것이 바로 SwiftUI가 부모 내부에서 10개 이상의 보기를 허용하지 않는 이유입니다. 그들은 2개에서 10개까지의 보기를 처리하지만 그 이상은 처리하지 않는 TupleView 버전을 작성했습니다.
두 번째 질문에 대해 Swift는 @ViewBuilder라는 body property에 특수 속성을 자동으로 적용합니다. 이것은 TupleView 컨테이너 중 하나에서 여러 view를 자동으로 래핑하는 효과가 있으므로 여러 view를 다시 보내는 것처럼 보이지만 하나의 TupleView로 결합됩니다.
이 동작은 마술이 아닙니다. View 프로토콜을 마우스 오른쪽 버튼으로 클릭하고 "Jump to Definition"을 선택하면 body 속성에 대한 요구 사항과 @ViewBuilder 속성으로 표시되는 것을 볼 수 있습니다.
@ViewBuilder var body: Self.Body { get }
물론 SwiftUI가 스택 없이 되돌아가는 여러 뷰를 해석하는 방법은 어디에도 구체적으로 정의되어 있지 않지만 나중에 배우게 될 것이므로 실제로 도움이 됩니다.
https://velog.io/@oto/ViewBuilder
https://www.hackingwithswift.com/books/ios-swiftui/why-does-swiftui-use-some-view-for-its-view-type