TLDR is it possible to update a single published property in a ViewModel without causing the entire View that observes it to reload?
I have a Lottie animation on a subview, and am using Firebase Realtime Database to observe changes from a cloud object. When using MVVM, anytime a property receives a change from Firebase the entire view re-loads, causing my animation to start again. I need to maintain an observer of Firebase as other UI changes require a dynamic update, however when any one of them change I don't want to re-draw the entire view (and subsequently set off my animation).
I've tried both @EnvironmentObject and @StateObject (simplified version seen here), as well as using !=
as a way of preventing an update to the local data from Firebase unless it's different. I've read about Equatable
(link), however not sure if that's applicable here? Is it possible to update individual properties and have the view respond specifically to them only? Thanks!
// SomeViewModel() gets created in the App struct
// Main View
struct ContentView: View {
@StateObject var someViewModel: SomeViewModel
var body: some View {
LottieView(someViewModel: someViewModel)
}
}
// Subview
struct LottieView: View {
@StateObject var someViewModel: SomeViewModel
var body: some View {
Lottie(name: someViewModel.lottieToShow, loopMode: .playOnce)
.frame(width: 250, height: 250)
}
}
// ViewModel
class SomeViewModel: ObservableObject {
@Published var lottieToShow: String = "lottie_city_animation"
@Published var someOtherProperty: Bool = false
private var isCity: Bool = false { didSet {
updateLottie()
}}
private func updateLottie() {
if isCity == true {
self.lottieToShow = "lottie_city_animation"
} else {
self.lottieToShow = "lottie_park_animation"
}
}
// Firebase
private func readObject() {
ref.child("users").child("01")
.observe(.value) { snapshot in
do {
let firebaseObject = try snapshot.data(as: Object.self)
if self.isCity != firebaseObject.isCity {
self.isCity = firebaseObject.isCity
}
if self.someOtherProperty != firebaseObject.someOtherProperty {
self.someOtherProperty = firebaseObject.someOtherProperty
}
} catch {
print("Error reading value")
}
}
}
}