When using @EnvironmentObject, can you have an @EnvironmentObject inside of another class?
I have a setup (MeetingStats) class and then a processing class(Meeting). The processing class and the setup classes are both displayed via different tabs in my app. So if you can change the settings in setup, you should see in real time the changes to the processing class (that is mostly timer driven).
I have tried to switch from using the AppDelegate to passing things between views, to using @EnvironmentObject. I have changed my ScceneDelegate to create the initial objects, and am passing them .envrionmentObjects to the ContentView. However, when I run the app, the first time I try to access the setup class in the processing class, I crash with the message No ObservableObject of type MeetingStats found. A View.environmentObject(_:) for MeetingStats may be missing as an ancestor of this view.
SceneDelegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var meetingStats = MeetingStats()
var meeting = Meeting()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
{
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
// passing EnvironmentObjects
window.rootViewController = UIHostingController(rootView:
ContentView()
.environmentObject(meeting)
.environmentObject(meetingStats)
)
self.window = window
window.makeKeyAndVisible()
}
}
}
Content View is a set of tabs, one for meeting, one for setup and one for statistics
meeting.swift - grossly simplified to show the problem area
//
// meeting.swift
import Foundation
import SwiftUI
import Combine
import Intents
import os
class Meeting: ObservableObject {
@EnvironmentObject var meetingStats: MeetingStats
@objc func calcQuorumEvents() {
// LOTS of calcualtions
self.meetingStats.totalWasteAmount = totalWasteAmount. // HERE's the Crash
self.meetingStats.totalWasteAmountPersonal = totalWasteAmountPersonal
self.meetingStats.totalLifetimeWasteAmount = totalLifetimeWasteAmount
}
}
Is the issue I am not passing explicitly passing the values to the tabs from the contentView? I have tried explicitly passing the Environment object to the meetingView but still receive the same error:
iOSMeetingView()
.environmentObject(meeting)
.environmentObject(meetingStats)
.tabItem {
Image("presentation")
Text("Meeting")
}.tag(1)
I didn't think that was required as Swift was to look in the object hierarchy to find the object.
Did you add the environment objects in view iOSMeetingView?
@EnvironmentObject var meetingStats: MeetingStats
Edited: I am not sure about your requirement. Here is my thought. Pass EnvironmentObject meetingStats only to view and you will get the value changes of meetingStats while updating in Meeting.
class Meeting {
func calcQuorumEvents(meetingStats: MeetingStats) {
meetingStats.totalWasteAmount = 12 // HERE's the Crash
meetingStats.totalWasteAmountPersonal = 60
meetingStats.totalLifetimeWasteAmount = 8
}
}
class MeetingStats: ObservableObject {
@Published var totalWasteAmount: Int
@Published var totalWasteAmountPersonal: Int
@Published var totalLifetimeWasteAmount: Int
init() {
totalWasteAmount = 0
totalWasteAmountPersonal = 0
totalLifetimeWasteAmount = 0
}
}