이런 듣도보다 못한 뷰 파일을 본 적이 있는가? 대부분의 SwiftUI의 뷰는 Computed Property를 이용하여 만드는데, 저런식으로 만드는건 상상조차 못했을 일이다.
하지만 body조차 프로퍼티이기 때문에, 안될 일이 무엇이 있겠는가.
오늘은 View 프로토콜은 무엇인지 알아보려고 한다.
SwiftUI View의 시작이자 끝이기 때문에, 뭔가 되게 엄청 많을 것 같지만, protocol자체에는 주석을 제외하면 이것밖에 없다.
public protocol View {
associatedtype Body : View
@ViewBuilder @MainActor var body: Self.Body { get }
}
View프로토콜 내부에 View 프로토콜을 가지는 Body에다가 Body 타입을 받는 body프로퍼티를 만들라고 하는것이 끝이다.
사실 그 아래에 Extension으로 View에서 사용할 수 있는 Modifier들이 만들어져 있긴 하다.
extension View {
public func accessibilityShowsLargeContentViewer<V>(@ViewBuilder _ largeContentView: () -> V) -> some View where V : View
// ....
}
프로토콜 자체는 이런것 밖에 없으니 다른 단서를 찾으려면 어떤걸 봐야할까?
@resultBuilder public struct ViewBuilder {
/// Builds an expression within the builder.
public static func buildExpression<Content>(_ content: Content) -> Content where Content : View
/// Builds an empty view from a block containing no statements.
public static func buildBlock() -> EmptyView
/// Passes a single view written as a child view through unmodified.
///
/// An example of a single view written as a child view is
/// `{ Text("Hello") }`.
public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
public static func buildBlock<each Content>(_ content: repeat each Content) -> TupleView<(repeat each Content)> where repeat each Content : View
}
@resultBuilder에 대해선 나중에 다뤄 보도록 하고, 기존에 나는 ViewBuilder를 사용하면 이게 뷰라는걸 인정해주는 (,,,??) 그런 키워드라고 생각했었는데, 열어보니까 상당히 재미있는 것들이 많았다. buildBlock이라는 메서드도 상당히 재밌는것 같기도 하고,,
ViewBuilder의 정의는 다음과 같다.
SwiftUI ) ViewBuilder
Closure에서 View를 구성하는 custom parameter attribute
사실 이 설명도 크게 와닿지 않아서 한번 더 쉽게 설명하자면,
Closure안에 써놓은 여러 뷰들을 하나의 단일 뷰로 만들어주는 녀석
이게 무슨 소리인가 싶은데, SwiftUI에서의 View는 Stack, Group등으로 묶을수가 있는데, 이걸 단순하게 하나의 뷰로 만들어주겠다는 의미이다.
View의 some View를 맨 윗처럼 자세하게 타입을 명시하게 된다면 이런식으로 작성할 수 있을 것이다.
struct ContentView: View {
var body: VStack<TupleView<(Text,Text)>> {
VStack {
Text("")
Text("")
}
}
}
이렇게 타입을 보게 되면 또 이해가 될 수 있을거라고 생각한다.
ViewBuilder는 여러 뷰들을 하나의 단일 뷰로 만들어주는 녀석...
ViewBuilder가 저렇게 하나의 타입으로 만들어 알아서 Return을 해주고 있었던 것이다. 아마 역제네릭이나 ViewBuilder가 없었다면.. (끔찍)