SwiftUI: Do czego służy @Binding?
Czym jest @Binding?
W SwiftUI możesz łatwo tworzyć aplikacje za pomocą kilku widoków. Jeden widok może składać się z kilku innych.
W niektórych przypadkach będzie potrzeba dzielenia się danymi między widokiem: rodzic a widokiem: dziecko. Ale to nie wszystko. Może być taka potrzeba, że wartość przekazana między widokami powinna być modyfikowana przez oba widoki, a ewentualne zmiany, powinny być widoczne w obu widokach.
Można to ująć krócej: @Binding pozwala na stworzenie komunikacji dwukierunkowej między widokami.
Użycie @Binding idzie w parze z użyciem @State. @State używasz w widoku rodzica, a @Binding w widoku dziecka.
Przykład
Pierwszy widok:
import SwiftUI
struct CounterView: View {
@Binding var counter: Int
var body: some View {
VStack {
Text("\(counter)")
.font(.largeTitle)
HStack {
Button("+") {
counter += 1
}.padding()
Button("-") {
counter -= 1
}.padding()
}
}
}
}
Za pomocą @Binding jest tworzone wiązanie dwukierunkowe między widokami.
Drugi widok:
import SwiftUI
struct ContentView: View {
@State private var counter: Int = 0
var body: some View {
VStack {
CounterView(counter: $counter).padding()
Button("RESET") {
counter = 0
}
}
}
}
#Preview {
ContentView()
}
Zmienna counter przekazywana jest do widoku CounterView. Ponieważ ten widok, jako parametr przyjmuje wiązanie, musisz użyć znaku dolara: $counter.
Kiedy stan zmiennej counter zostanie zmieniony w widoku CounterView będzie to widoczne także w widoku rodzica (ContentView).
Wartość licznika można też zmienić w ContentView i ta zmiana także zostanie przekazana do widoku dziecka (CounterView).
Preview i @Binding
Zakładając, że widok przyjmuje parametr jako @Binding, jak należy przekazać wartość w Preview?
Nie możesz zrobić tak:
#Preview {
CounterView(arg: 0)
}
Zostanie zgłoszony błąd!
Żeby rozwiązać ten problem, możesz:
a) Użyć Binding.constant. Tworzy ona wiązanie z niezmienną wartością.
#Preview {
CounterView(arg: .constant(10))
}
Problem z tym rozwiązaniem jest taki, że nie możesz zmienić wartości przekazanej jako constant w widoku.
Możesz to obejść za pomocą drugiego sposobu:
b) Przekazać wartość w zmiennej/stałej używając znaku dolara: $:
#Preview {
struct PreviewWrapper: View {
@State var counter: Int = 1
var body: some View {
CounterView(counter: $counter)
}
}
return PreviewWrapper()
}