ViewBuilder 는 어떻게 만드는 걸까? - ②

2023. 10. 7. 21:22Mobile/SwiftUI

앞서 ViewBuilder의 개념에서 하위 뷰 생성 클로저에 매개변수에 대한 속성으로 사용해 해당 클로저가 여러 하위 뷰를 제공할 수 있도록 해준다고 한다. 는 걸 알아봤다. 그런데 뷰빌더를 어떻게 만들어서 갖다쓰는 걸까?! 

 

custom container view 를 만들어서 레고 블록처럼 가져다 쓸수 있다고 해야할까..

하위 뷰는 뷰 선언부를 작고 가볍게 재사용할 수 있는 블록으로 나누는 방법을 제공한다. 

 

하위 뷰에는 한계가 있는 컨테이너 뷰의 콘텐트가 정적이기 때문에 하위 뷰가 레이아웃(Layout) 에 포함될 시점에 하위 뷰에 포함될 뷰를 동적으로 지정할 수 없다. 

 

우선 백문이불여일타라고, 눈으로 보고, 코드부터 짜봤다. 

 

@ViewBuilder 를 생성하기 위한 조건. 

1. <Content: View> 라는 제너릭 타입같은 놈을 붙여준다. Content 는 가져다 쓸 레고블럭 같은 속성을 만들어주기 위해 이름 붙여준 View 다 

2. struct customView: View 안에 

     let content : () -> Content (만들어줄 커스텀 뷰) 의 녀석을 반환하게 넣어줬다.

3. 아래  클로저 생성하고 반환은 Content 타입으로 반환하는 이니셜라이저를 만들었다. 

init(@ViewBuilder content: @escaping () -> Content) {
	self.content = content  
}

전체코드를 살펴보면, 나는 Text 에 그라디언트 색상을 커스텀하게 컴포넌트화 해서 갖고 오고 싶어서 이렇게 짜봤다.

struct MyVStack<Content: View>: View {
	
	let content: () -> Content
	init(@ViewBuilder content: @escaping () -> Content) {
		self.content = content
	}
	
	var body: some View {
		
		VStack(spacing: 20) {
			
			content()
				.foregroundStyle(
					LinearGradient(
						colors: [.orange, .blue],
						startPoint: .bottomLeading,
						endPoint: .topTrailing)
				)	
		}
		.font(.largeTitle)
		
	}
}

커스텀한 MyVStack 뷰를 구현하기위해 ViewBuilder 속성을 사용했고,  


struct ContentView: View {
	var body: some View {
		
			NavigationView {
				
				VStack {
					HStack {
						Text("iOS 17")
							.font(.title2)
							.fontWeight(.black)
							.padding(24)
					}
					
					MyVStack {
						Text("iPhone 13 pro")
						Text("iPhone 14 pro")
						Text("iPhone 15 pro")
					} //: MyVStack
					
					HStack {
						Image(systemName: "iphone.gen2")
						Image(systemName: "iphone")
						Image(systemName: "iphone")
					}//: HStack
					.padding(10)
					.font(.largeTitle)
					Spacer()
				}//: VStack
				.navigationTitle("View Builder")
				.padding(24)
			} //: NavigationView
	}
}

 

 

구현화면 

 

 

이렇게 각각의 다른 뷰들마다 적용하고 싶은 속성을 구분해서 줄 수 있다.

NavigationView 안에 

VStack 안에 

- HStack 

- MyVStack( ViewBuilder 로 속성 줌 )

- HStack 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


추가되면 좋을만한 정보나, 잘못된 정보에 대한 피드백 환영합니다.  

+ ) 자가 피드백 _ 2023.11.3

(iOS 13.0 - 17.2) NavigationView 가 Deprecated 될 예정이다. NavigationStack 으로 대체하는 것을 권장한다.