I am working with SwiftUI and @EnvironmentObjects. I am using the SwiftUI App Lifecycle. In this file I create a @StateObjects for ListingRepository and attach it to ContentView() with .envrionmentObjects().
struct MyApp: App {
// @EnvironmentObjects
@StateObject private var listingRepository = ListingRepository()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(listingRepository)
}
}
}
My assumption was that I could now access listingRepository by using an @EnvironmentObject wrapper. However, it seems I must instantiate this again. Below is my ListingViewModel. My first attempt looked like the following.
class MarketplaceViewModel: ObservableObject {
@EnvironmentObject var listingRepository: ListingRepository
@Published var listingRowViewModels = [ListingRowViewModel]()
private var cancellables = Set<AnyCancellable>()
init() {
listingRepository
.$listings
.receive(on: RunLoop.main)
.map { listings in
listings.map { listing in
ListingRowViewModel(listing: listing)
}
}
.assign(to: \.listingRowViewModels, on: self)
.store(in: &cancellables)
}
}
This threw the following error.
Fatal error: No ObservableObject of type ListingRepository found. A View.environmentObject(_:) for ListingRepository may be missing as an ancestor of this view.
The second option uses @Published and fixes the error.
class MarketplaceViewModel: ObservableObject {
@Published var listingRepository = ListingRepository()
@Published var listingRowViewModels = [ListingRowViewModel]()
private var cancellables = Set<AnyCancellable>()
init() {
listingRepository
.$listings
.receive(on: RunLoop.main)
.map { listings in
listings.map { listing in
ListingRowViewModel(listing: listing)
}
}
.assign(to: \.listingRowViewModels, on: self)
.store(in: &cancellables)
}
}
My questions are the following.
- Is it necessary to instantiate twice like I am?
- Why doesn't the instantiation in @main App work?