Reputation: 4833
In order to have my iOS/iPadOS app working well with multiple windows, I'd like to divide app state into 'app state' (eg. data layer, state of in app purchases etc.) and 'window state' (with UI state variables specific for a single window, like isDetailViewOpen
).
Here is how I imagined it:
App.swift:
import SwiftUI
@main
struct WeathergraphApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject var appState: AppState
var body: some Scene {
WindowGroup {
ContentView(appState: appState)
}
}
}
ContentView.swift:
import SwiftUI
struct ContentView: View {
@StateObject var windowState = WindowState()
@ObservedObject var appState: AppState
var body: some View {
ZStack(alignment: Alignment.top) {
MyViewView(appState: appState, windowState: windowState)
}
.sheet(isPresented: $windowState.purchasesIsPresented) {
PurchasesView(appState: appState)
} // I am referring to windowState here, so that one window can have purchases popup open, while other won't
}
}
However, Swift won't compile my App.swift
with an error Protocol requires initializer 'init()' with type '()'
.
Any idea how to have a shared app state without resorting to singletons (or @Environment, which seems same to me)?
Upvotes: 0
Views: 982
Reputation: 29251
The issue is likely here
@StateObject var appState: AppState
It should be something like
@StateObject var appState: AppState = AppState()
It can't come from another View
or the AppDelegate
. @StateObject
is a property wrapper type that instantiates an observable object.
Then pass it along with
@EnvironmentObject var appState: AppState
not an @ObservedObject
https://developer.apple.com/documentation/swiftui/stateobject
If you initialization is coming from the AppDelegate
you will likely solve your error by switching @StateObject var appState: AppState
to @ObservedObject var appState: AppState
and then continue passing it along with @EnvironmentObject
.
Just as a word of caution from my experience and other experiences I've read in SO the Observable Object property wrappers only seem to work effectively for 2 or 3 layers any deeper and you start getting inconsistencies.
Upvotes: 2