Reputation: 2034
I am building a multiplatform app for iOS/iPadOS/macOS and would like to be able to open multiple windows of the same application on macOS.
This feature comes out of the box when you use WindowGroup and I'm able to open a new window from the status bar. However, I'm having trouble with separating state that should be shared and state that should be local to the windows.
Here's a stripped down version of my current app entry point. When opening a new window, I would like to ensure that the api
state object is shared across all opened windows, but the navManager
object should maintain it's own state per opened Window.
import SwiftUI
@Observable class NavManager {
enum NavItem {
case a
case b
}
var currentNav: NavItem = .a
}
@Observable class Api {
var someProperty: String = "Hello World"
}
struct NavigationView: View {
@State private var navManager: NavManager = NavManager()
var body: some View {
switch navManager.currentNav {
case .a:
Text("Navigated to a")
case .b:
Text("Navigated to b")
}
Button {
if navManager.currentNav == .a {
navManager.currentNav = .b
} else {
navManager.currentNav = .a
}
} label: {
Text("Toggle navigation")
}
Text("Some subview hierarchy that needs navManager")
.environment(navManager)
}
}
@main
struct MPFApp: App {
@State private var api: Api = Api()
var body: some Scene {
WindowGroup {
NavigationView()
.environment(api)
}
}
}
Unfortunately with this code the state maintained in navManager is still shared between both windows, meaning navigation in one, will automatically navigate in the other window.
I couldn't find a clear description for this on the apple website or their WWDC talks. Any help would be much appreciated!
Kind regards, Thiezn
UPDATE: This functionality is now working properly. Ensure not to initialize the NavManager in your App view, but initialize it inside of NavigationView.
Upvotes: 3
Views: 273
Reputation: 2034
This functionality is now working properly. Ensure not to initialize the NavManager in your App view, but initialize it inside of NavigationView.
Upvotes: 0
Reputation: 90
For anyone encountering the same issue, I also filed a bug report to Apple.
Meanwhile, I was able to work around the issue using non-default WindowGroup
initializer:
@main
struct ExampleApp: App {
var body: some Scene {
// A dummy type to force root-view instantiation per window:
WindowGroup(for: UUID.self) { _ in
Test()
}
}
struct Test: View {
init() {
Logger().debug("Test init")
}
var body: some View {
Text("Test")
}
}
In this way, I see "Test init" printed per each new window, which was not true with default WindowGroup { ... }
initializer.
Upvotes: 2