Kurz zusammengefasst: ObservableObject
-
Mit dem Property-Wrapper @Published-ausgezeichnete Eigenschaften sind als Combine-Publisher einzeln beobachtbar (Eigenschaft xyz kann als $xyz via Combine abonniert werden)
-
Mit @Published deklarierte Eigeschaften lösen eine Benachrichtigung des objectWillChange-Publishers des Objektes aus
-
Wird ein ObservableObject in SwiftUI als @StateObject, @ObservedObject oder @EnvironmentObject verwendet, erfolgt automatisch eine Aktualisierung des Views bei Änderungen an @Published-Eigenschaften.
Beispiel:
class CounterModel: ObservableObject {
@Published var value = 0
func increment() {
self.value += 1
}
}
struct ContentView: View {
@StateObject var counterModel = CounterModel()
var body: some View {
VStack {
Text("Counter value \(self.counterModel.value)")
.padding()
Button("Increment") {
self.counterModel.increment()
}
}
}
}
Stolperfallen
-
Es heißt objectWillChange: Die Benachrichtigung erfolgt, bevor der neue Wert gesetzt wird (u.U. ungünstig wenn mehrere Werte in Kombination abonniert werden sollen - ObservableObject ist super für SwiftUI-"auto refresh" aber eher nicht für komplexere "reactive data flows")
-
Wenn ein ObservableObject Eigenschaften enthält, die als class deklariert sind (Referenz-Semantik), erfolgt nur eine Änderungsbenachrichtigung wenn sich die Referenz ändert, nicht die Inhalte des referenzierten Objektes.
Empfehlung: Ausschließlich struct/enum-Typen für Eigenschaften verwenden -
Vererbung funktioniert erst ab iOS 14.5 korrekt:
@Published property wrapper not working on subclass of ObservableObject -
Es gibt eine Möglichkeit, ObservableObjects ineinander zu verschachteln und eine rekursive Änderungsbenachrichtigung zu implementieren (Empfehlung: eher nicht):
Nested ObservableObjects