SwiftUI: Do czego służy @Binding?

Opublikowano: 04.01.2024 - tagi: SwiftUI Swift Widok Stan

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()
}