728x90
728x90
ViewBuilder
A custom parameter attribute that constructs views from closures.
@resultBuilder struct ViewBuilder
SwiftUI ์์ ViewBuilder ๋ ํด๋ก์ ธ๋ฅผ ํตํด ๋ทฐ ๊ณ์ธต์ ์ ๋ฌํ ์ ์๋ ์์ฑ์ด๋ค.
- ViewBuilder ๋ฅผ ์ด์ฉํ๋ฉด ํจ์๋ ํด๋ก์ ๋ ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ๋ฐํํ ์ ์๋ค.
- ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ์ ๋ฌํด์ผํ๋ ์ํฉ์์ ์ฝ๋๋ฅผ ๊น๋ํ๊ฒ ์์ฑํ ์ ์๋ค.
๐ฏ resultBuilder ?
- ViewBuilder ๋ @resultBuilder ํ๋กํผ๋ฆฌ ๋ํผ๊ฐ ๋ถ์ด ์๋๋ฐ ํด๋น ์์ฑ์ Swift5.4 ์ ๋์
๋์๊ณ ๊ธฐ์กด ๋ช
์นญ์ @_functionBuilder ์ด๋ค.
- SE-0289์ ResultBuilder
- resultBuilder ๋ ๋ทฐ์ ํ์ ๋์ง ์๊ณ ํจ์, ํ๋กํผํฐ, ํ์ ์ ํ์ฉ๋ ์ ์๋ ํํ๋ก ์ปค์คํ ํ ๋ฌธ๋ฒ์ ๊ฐ์ง ๋น๋๋ฅผ ์์ฑํ ์ ์๋ค.
- ViewBuilder, resultBuilder ๋ DLS(Declarative Language Structures, ์ ์ธ์ ์ธ์ด ๊ตฌ์กฐ) ์ ์ผ์ข ์ผ๋ก ๋ณผ ์ ์๋ค.
- ์๋ ์์๋ฅผ ๋ณด๋ฉด @NumberListBuilder ๋ฅผ ์ฌ์ฉํ ๋ฉ์๋์ ์ค๋ฐ๊ฟ์ผ๋ก ์์ฑ๋ 1, 2, 3 ์ ๋ฐฐ์ด๋ก ๋ณํํ ์ ์๋ค.
@resultBuilder
struct NumberListBuilder {
static func buildBlock(_ numbers: Int...) -> [Int] {
numbers
}
}
@NumberListBuilder
func makeNumberList() -> [Int] {
1
2
3
}
let numbers = makeNumberList()
print(numbers) // ์ถ๋ ฅ: [1, 2, 3]
- HTMLBuilder ๋ฅผ ๋ง๋ค์ด html ๊ตฌ์กฐ๋ฅผ ์์ฑํ ์ ์๋ ์์
@resultBuilder
struct HTMLBuilder {
static func buildBlock(_ components: HTMLComponent...) -> String {
components.map { $0.htmlString }.joined()
}
}
protocol HTMLComponent {
var htmlString: String { get }
}
struct TextComponent: HTMLComponent {
let text: String
var htmlString: String {
"<p>\(text)</p>"
}
}
struct LinkComponent: HTMLComponent {
let text: String
let url: String
var htmlString: String {
"<a href=\"\(url)\">\(text)</a>"
}
}
func createHTML(@HTMLBuilder content: () -> String) {
let html = content()
print(html)
}
createHTML {
TextComponent(text: "Hello, World!")
LinkComponent(text: "OpenAI", url: "https://openai.com")
TextComponent(text: "Welcome to Swift programming!")
}
- Regex builder DSL ๋ ์์๋ก ๋ณผ ์ ์๋ค.
import RegexBuilder
let emailPattern = Regex {
let word = OneOrMore(.word)
Capture {
ZeroOrMore {
word
"."
}
word
}
"@"
Capture {
word
OneOrMore {
"."
word
}
}
} // => Regex<(Substring, Substring, Substring)>
let email = "My email is my.name@mail.swift.org."
if let match = try emailPattern.firstMatch(in: email) {
let (wholeMatch, name, domain) = match.output
// wholeMatch: "my.name@mail.swift.org"
// name: "my.name"
// domain: "mail.swift.org"
}
ViewBuilder ํ์ฉ - ์์๋ทฐ ์ ๋ฌ
๋ฉ์๋์ ํด๋ก์ ธ ํ๋ผ๋ฏธํฐ์ @ViewBuilder ๋ฅผ ๋ถ์ฌ ์์๋ทฐ๋ฅผ ์ ๋ฌํ ๋ ์ฌ์ฉํ ์ ์๋ค.
- contextMenu ๋ผ๋ ๋ฉ์๋๋ฅผ ํตํด ์ฌ๋ฌ๊ฐ์ ์์๋ทฐ๋ฅผ ์ ๋ฌํ ์ ์๋ค.
- ํน์ ํ View ๋ฅผ ๋ง๋ค๊ณ ์ฌ๋ฌ๊ฐ์ ์์๋ทฐ๋ฅผ ์์ฑ์ผ๋ก ๊ฐ๋๋ก initializer ์์ ์ ๋ฌํ ์ ์๋ค.
struct Stack<Content: View>: View {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
VStack {
content()
}
}
}
Stack {
Text("Cut")
Text("Copy")
Text("Paste")
}
ViewBuilder ํ์ฉ - computed property, method
View ๊ตฌ์กฐ์ฒด ์ฝ๋ ๋ด์์๋ง ์ฌ์ฉ๋๋ ๊ฐ๋จํ ๋ทฐ์ ๋ํด computed property ํน์ method ๋ก ๋บ ๊ฒฝ์ฐ์ ํ์ฉํ ์ ์๋ค.
- ๋จ์ผ ๋ทฐ๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ์์๋ @ViewBuilder ๋ฅผ ๋ถ์ด์ง ์์๋ ๋์ง๋ง,
- ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ๋ฐํํ๋ ๊ฒฝ์ฐ @ViewBuilder ๋ฅผ ๋ถ์ด์ง ์์ผ๋ฉด ์ปดํ์ผ ์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค.
- computed property ์์ ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ๋ฐํํ๋ ์ฝ๋
- ํด๋น ์ฝ๋์์ ViewBuilder ๋ฅผ ๋ถ์ด์ง ์์ผ๋ฉด ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ์๋๋ค.
struct ContentView: View {
@ViewBuilder
var greeting: some View {
if shouldShowGreeting {
Text("Hello, SwiftUI!")
Text("Welcome to the world of SwiftUI!")
} else {
EmptyView()
}
}
var shouldShowGreeting: Bool = true
var body: some View {
VStack {
greeting
}
}
}
- computed property ์์ ๋จ์ผ ๋ทฐ๋ฅผ ๋ฐํํ๋ ์ฝ๋
- ํด๋น ์ฝ๋์์๋ ViewBuilder ๊ฐ ์์ด๋ ๋๋ค
struct ContentView: View {
var shouldShowGreeting: Bool = true
var greeting: some View {
if shouldShowGreeting {
return Text("Hello, SwiftUI!")
} else {
return Text("Goodbye, SwiftUI!")
}
}
var body: some View {
VStack {
greeting
}
}
}
- method ์์ ์ฌ๋ฌ๊ฐ์ ๋ทฐ๋ฅผ ๋ฐํํ๋ ์ฝ๋
struct ContentView: View {
var shouldShowGreeting: Bool = true
var body: some View {
VStack {
greeting(shouldShowGreeting)
}
}
@ViewBuilder
func greeting(_ shouldShowGreeting: Bool) -> some View {
if shouldShowGreeting {
Text("Hello, SwiftUI!")
Text("Welcome to the world of SwiftUI!")
} else {
EmptyView()
}
}
}
์ฐธ๊ณ ๋ฌธ์
728x90
728x90
'๐ iOS > SwiftUI' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] SwiftUI - GeometryReader / View ํฌ๊ธฐ์ ์ขํ ๊ณ์ฐํ๊ธฐ (1) | 2023.10.21 |
---|---|
[iOS/SwiftUI] @Environment ์์๋ณด๊ธฐ / ๋ชจ๋ฌ ๋ทฐ ๋ซ๊ธฐ dismiss ํ์ฉ (0) | 2023.06.15 |
[iOS] SwiftUI LazyVStack LazyHStack :: lazy load views (1) | 2022.06.07 |
[iOS] SwiftUI property wrapper @State @Binding (0) | 2022.06.02 |
[iOS/SwiftUI] Text, Image ๊ธฐ๋ณธ ์ ๋ฆฌ + ์์คํ ์ด๋ฏธ์ง (0) | 2022.05.05 |