Definition
@resultBuilder
struct ViewBuilder
ํด๋ก์ ์์ ๋ทฐ๋ฅผ ๊ตฌ์ฑํ๋ ์ฌ์ฉ์ ์ง์ ํ๋ผ๋ฏธํฐ ์์ฑ
func contextMenu<MenuItems: View>(
@ViewBuilder menuItems: () -> MenuItems
) -> some View
ํด๋ก์ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด child view๋ฅผ ์์ฑํ๊ณ ์ ํ ๋ ViewBuilder๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ์์ ๊ฐ์ด ํ๋ผ๋ฏธํฐ๋ก ViewBuilder๋ฅผ ์ฌ์ฉํด ํด๋ก์ ๋ก child view๋ฅผ ํฌํจํ๋ ๋ทฐ๋ฅผ ์์ฑํ ์ ์๋ค.
myView.contextMenu {
Text("Cut")
Text("Copy")
Text("Paste")
if isSymbol {
Text("Jump to Definition")
}
}
contextMenu์ menuItems ํด๋ก์ ๋ก ์ฌ๋ฌ Text๋ฅผ ํฌํจํ๋ child view๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค.
์ฃผ๋ก ๋ณต์กํ ๋ ์ด์์์ ์ชผ๊ฐ์ด ์ฌ์ฉ์ ์ ์ ๋ทฐ๋ก ์์ฑํ๊ณ ์กฐํฉํ๋๋ฐ ์ฌ์ฉ๋๋ค.
so what is ViewBuilder
- custom parameter attribute
- custom : SwiftUI์ ์ํด ์ ์๋ ๊ฒ์ด ์๋ ์ฌ์ฉ์ ์ ์์ ์ํด ๋จ์ผ ๋ณตํฉ ๋ทฐ ์์ฑ ๊ฐ๋ฅ
- parameter : ํจ์๋ ์ด๋์ ๋ผ์ด์ ํ๋ผ๋ฏธํฐ ์์ ์์นํ๋ ํ๋ผ๋ฏธํฐ ์์ฑ
- attribute : ๋ฉํ๋ฐ์ดํฐ, ์ถ๊ฐ ์ ๋ณด๋ฅผ ํ๋ผ๋ฏธํฐ์ ์ฝ๋์ ์ ๊ณตํ๋ ์ญํ
- ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ๋จ์ผ ๋ณตํฉ ๋ทฐ(Composite View)๋ก ์กฐํฉ ๊ฐ๋ฅํ๊ฒ ํจ (๊ฐ์ธ์ ์ผ๋ก๋ ํด๋ก์ ๋ก ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ์ ๋ฌํ๋ค๊ธฐ ๋ณด๋ค๋ ๋ทฐ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ์ ๋ฌํ๋ค๊ณ ํ๋๊ฒ ๋ง๋ ๊ฒ ๊ฐ๋ค. view์ subview, ์ฌ๋ฌ view ์ ๋ฌ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์)
advantage
- ์ ์ฐ์ฑ
- ๋์ ์ผ๋ก ๋ทฐ๋ฅผ ์์ฑํ ์ ์์. ํด๋ก์ ๋ด๋ถ์์ ์กฐ๊ฑด๋ฌธ, ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ฌ ์ ์ฐํ๊ฒ ๋์ ๊ฐ๋ฅ
- ์์ ๋ทฐ์์ @ViewBuilder๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ ํ ๋ทฐ๋ ์ ๋ฌ ํ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ฐํ๊ฒ ์ปค์คํฐ๋ง์ด์ฆ ํ ์ ์์
VStack {
if isStart {
StartView()
} else {
InfoView()
}
}
- ์ฌ์ฌ์ฉ์ฑ
- ์ปค์คํ ๋ทฐ๋ฅผ ์์ฑํ์ฌ ๋์ผํ ๊ตฌ์ฑ์ ๊ฐ์ง๋ ๋ทฐ์์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํจ
- ์ฝ๋ ๊ฐ๊ฒฐ์ฑ
- ๋ทฐ ๋ก์ง์ ๋ถ๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณต์กํ UI๋ฅผ ๊ตฌ์ฑํ ๋ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ํ ์ ์์
- ๋ทฐ๋ฅผ ์์ ๋ถ๋ถ์ผ๋ก ์ชผ๊ฐ ๋ค ์กฐํฉํ์ฌ ๋ณต์กํ UI๋ฅผ ๊ตฌ์ฑํ ์ ์์ผ๋ฉฐ ์ ์ง๋ณด์ ์ธก๋ฉด์ ์ด์ ์ ๊ฐ์ง
disadvantage
- ๋ณต์ก์ฑ
- View๋ฅผ ๋ถ๋ฆฌํ๋ฏ๋ก์ ์๊ธฐ๋ ๋ณต์ก์ฑ์ผ๋ก ์ธํด ์ฝ๋์ ๋์ ์๋ฆฌ๋ฅผ ์ดํดํ๊ธฐ ํ๋ค๊ฒ ๋ง๋ค ์ ์์ผ๋ฉฐ ๊ฐ๋ ์ฑ์ ํด์น ์ ์์
- ๋๋ฒ๊น
- ์ฌ๋ฌ ๋ทฐ ๋ก์ง์ด ์ค์ฒฉ๋๋ฉด์ ์บก์ํ ๋๊ธฐ ๋๋ฌธ์ ํน์ ๋ฐ์ดํฐ๊ฐ ์ด๋์ ์ค๊ณ ์ด๋์ ์ฌ์ฉ๋๋์ง ์ถ์ ํ๊ธฐ ์ด๋ ค์ธ ์ ์์
- ๋ฐํ์ ์ด์
- ViewBuilder๊ฐ ์์ฑํ๋ ๋ทฐ์ ๊ฐฏ์์ ํ์ ์ด ์ปดํ์ผ ํ์ด๋ฐ์ ๊ฒฐ์ ๋๋ฉฐ ์ด๋ ํ์ ์์ ์ฑ๊ณผ ๋ฐํ์ ์ด์๋ฅผ ๋ฐ์์ํฌ ์ ์์
Example
@inlinable public init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content)
์ ์๋ฅผ ๋ณด๋ฉด ํ๋ผ๋ฏธํฐ๋ก @ViewBuilder๊ฐ ๋ถ์ ๊ฒ์ ํ์ธํ ์ ์๊ณ ์ด ํ๋ผ๋ฏธํฐ๋ ํด๋ก์ ๋ฅผ ํตํด ์ฌ๋ฌ ๋จ์ผ ๋ทฐ๋ฅผ ์ ๋ฌ ๋ฐ๋๋ค. ๋ทฐ ๋น๋๋ก ๋ถํฐ ์ ๋ฌ๋ ๋จ์ผ ๋ทฐ๋ค๋ก ๋ณตํฉ ๋ทฐ๋ฅผ ์์ฑํ ์ ์๋ค. ViewBuilder๋ฅผ ์ฌ์ฉํ๋ฉด ์ผ์ข ์ custom container๋ฅผ ๋ง๋ค ์ ์๋ค.
ViewBuilder๋ฅผ ์ฌ์ฉํด์ ์ปค์คํ ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๋ ๋ค๋ฅธ ํ๋ผ๋ฏธํฐ ์ธ์๋ก ๋ถํฐ ํ์ํ ๋ํ๋์๋ฅผ ํจ๊ป ์ ๋ฌ ๋ฐ์ ์ ์๋ค.
์์ ์ฝ๋
https://github.com/youabledev/viewbuilder_swiftui
struct NormalView<Content: View>: View { // ์ ๋ค๋ฆญ์ผ๋ก View๋ฅผ Content๋ก
let title: String
let buttonName: String
let content: () -> Content // ํด๋ก์ ๋ก ์ ๋ฌ ๋ฐ์
init(title: String, buttonName: String, @ViewBuilder content: @escaping () -> Content) {
self.title = title
self.buttonName = buttonName
self.content = content
}
var body: some View {
VStack(spacing: 0) {
ZStack {
Text(title)
.font(.system(.headline))
.fontWeight(.bold)
HStack {
Button {
} label: {
Image(systemName: "xmark")
.frame(width: 44, height: 44)
.foregroundColor(.black)
}
.padding(.leading, 14)
Spacer()
} //: HStack
} //: ZStack
.frame(maxWidth: .infinity)
.frame(height: 48)
Spacer()
content()
Spacer()
Button {
} label: {
Text(buttonName)
.foregroundColor(.white)
.padding(.vertical, 20)
.frame(maxWidth: .infinity)
.background(.black)
}
}
}
}
๊ณตํต์ผ๋ก ์ฌ์ฉ๋๋ View๋ฅผ ViewBuilder๋ฅผ ํตํด ์์ฑ
struct NormalView_Previews: PreviewProvider {
static var previews: some View {
NormalView(title: "์ ๋ชฉ", buttonName: "๋ฒํผ์ด๋ฆ") {
Text("ํ
์คํธ")
}
}
}
preview๋ฅผ ์ค์ ํด์ ๋ณด๋ฉด ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ ํ๋ฉด ์์ญ์ ViewBuilder ๋ฅผ ์ด์ฉํ View๋ก ์ง์ ํ ์ ์์ผ๋ฉฐ ํด๋ก์ ๋ฅผ ํตํด ํ์ํ ๋ทฐ๋ฅผ ์ ๋ฌํ ์ ์์
struct ProductDetailView: View {
var body: some View {
NormalView(title: "์ํ ์์ธ", buttonName: "๊ตฌ์
ํ๊ธฐ") {
GeometryReader { geometry in
VStack(alignment: .leading) {
Rectangle()
.frame(width: geometry.frame(in: .global).size.width - 48)
.frame(height: geometry.frame(in: .global).size.width - 48)
.foregroundColor(.yellow)
Text("๊ฐ๊ฒฉ : 20,000")
}
.padding(.horizontal, 24)
}
} //: NormalView
}
}
์ค์ ์ฌ์ฉํ ๋๋ ์ค๋ณต๋๋ ๋ทฐ ์ฝ๋๋ฅผ ์์ฑํ ํ์๊ฐ ์์ด ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ๋ณต์กํ ๋ทฐ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐ
ํ๊ฒ ๋ง๋ค ์ ์๋ค.
์ถ์ฒ ๋ฐ ์ฐธ๊ณ ์ฌ์ดํธ
'iOS ๐ > SwiftUI' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] NavigationView (1) | 2023.09.22 |
---|---|
[SwiftUI] ๊ฐ๋ก๋ชจ๋, ์ธ๋ก๋ชจ๋ ์ง์ํ๊ธฐ with @ViewBuilder (0) | 2023.09.20 |
[SwiftUI] Custom Font ์ง์ ํ๊ธฐ (with Figma) (2) | 2023.09.18 |
[SwiftUI] Link Text ๋ง๋ค๊ธฐ (๋ชจ๋ ๊ฑธ ์ค๋นํด ๋จ๋ค ๊ฐ์ ธ๋ค ์จ๋ผ!) (0) | 2023.08.27 |
[SwiftUI] bottom sheet ๋์ฐ๊ธฐ (0) | 2023.08.23 |