SwiftUI: Do czego służy @EnvironmentObject?
Opublikowano: 18.01.2024 - tagi: SwiftUI Swift Widok Wrapper Dane
Czym jest @EnvironmentObject?
Ten wrapper służy do wymiany danych między wieloma widokami. Jest to szczególnie przydatne kiedy jeden widok składa się z wielu innych i na przykład do niektórych z nich musimy przekazać jakieś dane.
Przekazywanie danych z jednego widoku do drugiego, aż w końcu trafimy na ten, w którym te dane są potrzebne, staje się męczące. Ten problem rozwiązuje @EnvironmentObject.
Masz także gwarancję, że jeśli dane się zmienią, widok zostanie automatycznie o tym poinformowany.
Aby przejąć dane oznaczone przez @EnvironmentObject, będziesz musiał w widoku, który znajduje się wyżej w hierarchii wywołać metodę environmentObject i przekazać do niej obiekt, którym chcesz się dzielić z innymi widokami.
Najlepiej wszystko zobrazuje poniższy przykład.
Przykład
Mamy jeden model o nazwie Counter.
Trzy widoki w takiej hierarchii: ContentView -> InformationView -> CounterLabelView.
Widok CounterLabelView potrzebuje mieć dostęp do obiektu klasy Counter. Dlatego w tym widoku zostanie użyty @EnvironmentObject, aby przechwycić przesłane dane.
W widoku InformationView niepotrzebny jest obiekt klasy Counter. Zawiera on widok CounterLabelView.
W widoku głównym ContentView wywołujemy metodę environmentObject, żeby przekazać instancję klasy Counter do widoków potomnych.
Model:
import SwiftUI
class Counter: ObservableObject {
@Published var value: Int = 0
func increment() {
value += 1
}
func decrement() {
value -= 1
}
func reset() {
value = 0
}
}
Pierwszy widok:
import SwiftUI
struct CounterLabelView: View {
@EnvironmentObject var counter: Counter
var body: some View {
Text("\(counter.value)")
.font(.largeTitle)
}
}
Drugi widok:
import SwiftUI
struct InformationView: View {
var body: some View {
VStack {
CounterLabelView()
Text("Click '+' to increment counter").padding()
Text("Click '-' to decrement counter").padding()
}
}
}
Główny widok:
import SwiftUI
struct ContentView: View {
@StateObject var counter = Counter()
var body: some View {
VStack {
InformationView()
HStack {
Button("+") {
counter.increment()
}.padding()
Button("-") {
counter.decrement()
}.padding()
}
}
.environmentObject(counter)
}
}