So I am still learning Swift and I can't seem to understand how to get around initializing an ObservedObject twice, so I wanted to see if I can get some help from the community.
So I have my App
file here:
@main
struct MapGlider: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
@ObservedObject var mainViewModel = MainViewModel()
var body: some Scene {
WindowGroup {
MainScreenContainer(
showOnboarding: $mainViewModel.showOnboarding
)
}
}
}
Which has my @ObservedObject var mainViewModel = MainViewModel()
listed inside.
Then inside MainScreenContainer
, I have the following items:
struct MainScreenContainer: View {
@ObservedObject var mainViewModel = MainViewModel()
@Binding var showOnboarding: Bool
var body: some View {
if showOnboarding {
OnboardingView(showOnboarding: $showOnboarding)
} else {
MainView()
.environmentObject(mainViewModel)
}
}
}
The problem with that is, inside my MainViewModel()
, I am initializing it twice on start, which gives me the following out:
2022-10-20 16:48:37.657849-0500 MapGlider[744:46395] Initialize: MainViewModel()
2022-10-20 16:48:37.745881-0500 MapGlider[744:46395] Initialize: MainViewModel()
Here is the sample code inside my MainViewModel()
observed object:
class MainViewModel: ObservableObject {
// MARK: - APP STORAGE
@AppStorage("showOnboarding") var showOnboarding = true
// MARK: - INIT
init() {
log.info("Initialize: MainViewModel()")
}
}
Is this normal behavior? If not, how do I prevent it being initilized twice on app start? How do I pass down the ObservedObject to other views without re-initializing it each time as I'm using MainViewModel()
inside MainView()
also.
CodePudding user response:
try this approach, passing the one source of truth, @StateObject var mainViewModel = MainViewModel()
to other views using @EnvironmentObject
:
@main
struct MapGlider: App {
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
@StateObject var mainViewModel = MainViewModel() // <-- here
var body: some Scene {
WindowGroup {
MainScreenContainer().environmentObject(mainViewModel) // <-- here
}
}
}
struct MainScreenContainer: View {
@EnvironmentObject var mainViewModel: MainViewModel // <-- here
var body: some View {
if mainViewModel.showOnboarding { // <-- here
OnboardingView(showOnboarding: $mainViewModel.showOnboarding) // <-- here
} else {
MainView()
}
}
}