swiftuienvironmentobject

SwiftUI view is not updating from environmentObject observable property


I'm connecting a firestore database to my UI.

I've created an SignedInAuthentication object which I set as an environment object

class SignedInAuthentication: ObservableObject {
    @Published var user: User
    @Published var workoutCompletionStore: WorkoutCompletionDataStoreProtocol

    init(user: User, workoutCompletionStore: WorkoutCompletionDataStoreProtocol) {
        self.user = user
        self.workoutCompletionStore = workoutCompletionStore
    }

    init(user: User) {
        self.user = user
        workoutCompletionStore = WorkoutCompletionDataStore(userId: user.userId)
    }
}

the WorkoutCOmpletionStore is implemented as follow:

class WorkoutCompletionDataStore: ObservableObject, WorkoutCompletionDataStoreProtocol {
    @Published var workoutCompletions: [WorkoutCompletion] = []
    private let userId: String?
 
    [...]

 func get() {
        guard let userId = userId
        else {
            workoutCompletions = []
            return
        }

        let fullPath = String(format: path, userId)
        store.collection(fullPath)
            .addSnapshotListener { querySnapshot, error in
                if let error = error {
                    AnalyticsWrapper.logError(message: "Error getting worKoutCompletions", error: error)
                    return
                }

                self.workoutCompletions = querySnapshot?.documents.compactMap { document in
                    try? document.data(as: WorkoutCompletion.self)
                } ?? []
            }
    }
[...]
}

The snapshot listener is called as expected. the list of workoutCompletion is updated (I'm removing and adding objects).

The problem I have is that the view that displays those workoutCompletion does not update after the WorkoutCompletionDataStore update its workoutCompletions when Firstore update fires.


struct HomeScreen: View {
    @ObservedObject var homeQueryData: HomeQueryData
    @AppStorage("didShowOnboarding") var didShowOnboarding: Bool = false
    @EnvironmentObject var signedInAuthentication: SignedInAuthentication


    func startChat() {
        let controller = UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.rootViewController
        Freshchat.sharedInstance().showConversations(controller!)
    }

    var body: some View {
        var workoutCompletions = signedInAuthentication.workoutCompletionStore.workoutCompletions
    [...]
}

What am I missing?


Solution

  • Thanks to @workingdog, I refactor my code so that WorkoutCompletionDataStore is a top level environment object and it is now working.

    Nesting Observable object does not seem to work.