SwiftUI 推出了兩個 Property Wrapper – @State and @Binding。利用它們可以達到變數的 Two-way Binding 功能。也就是當變數的值改變時,它會重新被顯示。本章藉由製作一個 Custom View 來展示如何使用 @State 和 @Binding。
@Binding
宣告一個 View 叫 CounterView。它主要顯示 counter 變數的值,然後有兩個 Button 可以加減 counter。
CounterView.counter 變數被宣告為 @Binding。如果只是單純的 var counter: Int,那 Parent View 傳值給 CounterView(counter:) 時,就只是單純的傳值。也就是說,不論 CounterView 怎麼設值給 CounterView.counter,Parent View 的 counter 都不會改變。
但是,加上 @Binding 後,CounterView.counter 會連結 (connect) Parent View 的 counter。所以當 CounterView 設值給 CounterView.counter 時 Parent View 的 counter 也會改變。
struct CounterView: View {
@Binding var counter: Int
var body: some View {
HStack {
Text(String(counter))
Button(action: { self.counter -= 1 }, label: { Text("-") })
Button(action: { self.counter += 1 }, label: { Text("+") })
}
.padding()
}
}
struct CounterView_Previews: PreviewProvider {
static var previews: some View {
CounterView(counter: .constant(0))
}
}@State
ContentView.counter 變數被宣告為 @State。所以當 counter 的值被變時,ContentView 就會被設為無效 (invalidated),導致 ContentView 被重新計算並重畫。這也就是雙向綁定 (Two-way Binding) 的使用。
但是這僅僅只限於在 ContentView 裡面。如果我們將 counter 變數傳給 CounterView,並希望當 CounterView 改變 counter 的值時,View 也可以被 Invalidated。那這就要靠 @Binding 的配合了。
因為 CounterView.counter 是宣告為 @Binding,那 ContentView 要傳 counter 給 CounterView 時,就要加上 $ 前綴符號。
struct ContentView: View {
@State var counter = 0
var body: some View {
VStack {
Text("Counter: \(counter)")
CounterView(counter: $counter)
}
}
}結語
@State 和 @Binding 是 SwiftUI 中很重要的一個功能。它們讓 SwiftUI 實現 Two-way Binding。讓開發者在管理 Parent View 和 Child Views 之間的變數,變得相當地容易,也易於了解。對於網頁開發者,這是很平常的事情,但對於 App 開發者而言,這是全新的開發方式。









