Search code examples
swiftmacosswiftuiappdelegate

SwiftUI macOS: Environment object in secondary window


I have a Mac app developer in Xcode 12.4.

I have found out how to setup and open a secondary window with NSApp.sendAction(#selector(AppDelegate.openSecondaryWindow), to: nil, from: nil). (Is there a better way?)

The problem is that I want to access in SecondaryView the same environment object globalState that ContentView has access to. How to do this?

My code:

class AppDelegate: NSObject, NSApplicationDelegate {
    var secondaryWindow: NSWindow!

    func applicationDidFinishLaunching(_ notification: Notification) {
       [...]
    }
    
    func applicationWillFinishLaunching(_ notification: Notification) {
        NSWindow.allowsAutomaticWindowTabbing = false
    }
    
    func applicationShouldTerminateAfterLastWindowClosed(_ app: NSApplication) -> Bool {
        return true
    }

    func applicationWillTerminate(_ notification: Notification) {
        [...]
    }
    
    @objc func openSecondaryWindow () {
        if self.secondaryWindow == nil {
            let secondaryView = SecondaryView()
            
            self.secondaryWindow = NSWindow(
                contentRect: NSRect(x: 20, y: 20, width: 480, height: 300),
                styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
                backing: .buffered,
                defer: false)
            self.spreadWindow.contentView = NSHostingView(rootView: secondaryView)
        }
        
        self.spreadWindow.makeKeyAndOrderFront(nil)
    }
}

@main
struct MyApp: App {
    @StateObject var globalState: GlobalState = GlobalState.shared
    
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
        
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(self.globalState)
        }
    }
}

Solution

  • Apply it directly to SecondaryView, like

        @objc func openSecondaryWindow () {
            if self.secondaryWindow == nil {
                let secondaryView = SecondaryView()
                    .environmentObject(GlobalState.shared)      // << here !!