본문 바로가기
iOS

SwiftUI: @ViewBuilder

by Dev Arthur 2025. 4. 16.

SwiftUI View 파일을 만들면 항상 기본적으로 작성되어 있는 var body: some View

나만의 Custom body 연산 프로퍼티를 만드는 것도 가능할까?

나도 만들래 나만의 var body: some view

성공✅!

받고 한 줄 더!

Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type

실패❌...

return을 명시적으로 적어달라고 얘기한다.

그래서 둘 중 하나의 인스턴스 앞에 return을 적어주면 일단, 오류는 해결(?)이 되긴 하는데 둘 중 하나만 적용이 된다❓...

그래서 하나의 묘책으로 두 인스턴스를 Stack이나 Group으로 묶어주니 이 부분도 해결이 되었다✅!

받고 분기처리까지 1!

성공✅!

받고 분기처리까지 2!

Conflicting arguments to generic parameter

실패❌...

제네릭 매개변수의 인자가 충돌한다라고 한다.

제네릭? some View는 제네릭이 아니라 불투명 타입이잖아?라고 할 수 있지만,

VStack의 내부 Content 인자가 제네릭 타입이다.

각 분기의 구체적인 타입은 VStack<TupleView<(Image, Image)>>VStack<TupleView<(Text, Text)>>라서 다른 타입이다.

또한, 보기에는 불투명 타입인 some View로 퉁칠 뿐이지 컴파일 타임에 구체적인 타입이 정해진다.

그렇기 때문에, 하나의 구체적인 타입으로 정해야 하는데,

위에서 말했듯 각 분기의 구체적인 타입이 서로 달라서 컴파일러가 오류를 내뱉고 있는 상황이다.

그래서 여기서도 받고 한 줄 더! 에서 사용했던 Group이나 Stack으로 묶으면 해결이 가능하다✅.

잠깐...? 그래도 내부에 여전히 분기문이 있으니까 해결이 안 돼야 하는 거 아닌가?

같은 의문과 함께, body 연산 프로퍼티는 어떻게 만들었길래 되는 거야?라는 의문이 들 것이다.

그래서 우선 View Protocol의 body가 어떻게 생겼는지 살펴보면,

3가지 Attribute가 붙어있는 걸 볼 수 있다.

MainActor와 preconcurrency는 잘은 모르더라도, 메인스레드의 동작과 동시성 관련 Attribute임을 예상할 수 있다.

그러면 나머지 하나인 @ViewBuilder에 대해 살펴보자.

ViewBuilder 공식문서

번역기의 힘을 빌려 해석했을 때, 중요한 부분은

...allowing those closures to provide multiple child views.
(...클로저가 여러 자식 뷰들을 제공하도록 허용한다.)
...can use multiple-statement closures to provide several child views...
(...여러 자식 뷰들을 제공하기 위해 다중상태 클로저를 사용할 수 있다...)

여기서 위 2가지 받고 한 줄 더! 받고 분기처리까지 2! 에서,

왜 기존의 body와 다르게 우리가 만든 custom body는 Stack이나 Group으로 묶어주는 묘책을 사용해야

오류를 해결할 수 있었는지 알 수 있다.

@ViewBuilder

- 여러 뷰들을 묶지 않아도 return 할 수 있도록 해주고,

- 분기에 따라 타입이 다르더라도 return 할 수 있도록 해준다.

 

그리고 잠깐...? 그래도 내부에 여전히 분기문이 있으니까 해결이 안 돼야 하는 거 아닌가? 에 대해서도 찾아보자면

VStack
Group

VStack과 Group 또한, 내부 content에 대해 @ViewBuilder를 적용시키고 있었기에 오류가 해결이 되었던 것이다.

반응형

'iOS' 카테고리의 다른 글

Swift: @retroactive  (0) 2025.05.31
UIKit: Frame과 Bounds 3  (0) 2025.01.13
UIKit: Frame과 Bounds 2  (0) 2025.01.10
UIKit: Frame과 Bounds 1  (0) 2025.01.05
Xcode: 영역  (0) 2025.01.01