I am working with SwiftUI and am using MVVM with my VM acting as my EnvironmentObjects.
I first create a AuthSession environment object which has a string for currentUserId stored.
I then create another environment object for Offers that is trying to include the AuthSession environment object so I can can filter results pulled from a database with Combine. When I add an @EnvironmentObject property to the Offer view model I get an error stating that AuthSession is not passed. This makes sense since it's not a view.
My question is, is it best to sort the results in the view or is there a way to add an EnvironmentObject to another EnvironmentObject? I know there is an answer here, but this model answer is not using VM as the EOs.
App File
@main
struct The_ExchangeApp: App {
// @EnvironmentObjects
@StateObject private var authListener = AuthSession()
@StateObject private var offerHistoryViewModel = OfferHistoryViewModel(offerRepository: OfferRepository())
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(authListener)
.environmentObject(offerHistoryViewModel)
}
}
}
AuthSession.swift
class AuthSession: ObservableObject {
@Published var currentUser: User?
@Published var loggedIn = false
@Published var currentUserUid = ""
// Intitalizer
init() {
self.getCurrentUserUid()
}
}
OfferHistoryViewModel.swift - The error is called just after the .filter in startCombine().
class OfferHistoryViewModel: ObservableObject {
// MARK: ++++++++++++++++++++++++++++++++++++++ Properties ++++++++++++++++++++++++++++++++++++++
// Access to AuthSession for filtering offer made by the current user.
@EnvironmentObject var authSession: AuthSession
// Properties
var offerRepository: OfferRepository
// Published Properties
@Published var offerRowViewModels = [OfferRowViewModel]()
// Combine Cancellable
private var cancellables = Set<AnyCancellable>()
// MARK: ++++++++++++++++++++++++++++++++++++++ Methods ++++++++++++++++++++++++++++++++++++++
// Intitalizer
init(offerRepository: OfferRepository) {
self.offerRepository = offerRepository
self.startCombine()
}
// Starting Combine - Filter results for offers created by the current user only.
func startCombine() {
offerRepository
.$offers
.receive(on: RunLoop.main)
.map { offers in
offers
.filter { offer in
(self.authSession.currentUserUid != "" ? offer.userId == self.authSession.currentUserUid : false) // ERROR IS CALLED HERE
}
.map { offer in
OfferRowViewModel(offer: offer)
}
}
.assign(to: \.offerRowViewModels, on: self)
.store(in: &cancellables)
}
}
Error
Thread 1: Fatal error: No ObservableObject of type AuthSession found. A View.environmentObject(_:) for AuthSession may be missing as an ancestor of this view.