Create and open a new document in SwiftUI DocumentGroup macOS

1.5k views Asked by At

How can I open a new document window in a SwiftUI ReferenceFileDocument-based app?

Background

This macOS app programmatically opens WindowGroups using .handleEvents(:). Unfortunately, this results in a File/New menu that wraps the names of those window groups with "New ... Window" (as pictured). Failing to find a way to override that wrapping, I tried to just just replace the New button and its menu entirely using a CommandGroup(replacing: .newItem) {}.

Yet, I also failed to remake the "create and open a new document window" command. I've tried searching for some Notification to post and applying .handleEvents. That only makes the existing open document window become the key window. Without an open document, it does nothing.

Undesired wrapping

enter image description here

@main
struct TheApp: App {
    
    @StateObject var root: RootStore
    
    var body: some Scene {
        DocumentGroup { ProjectDocument() } editor: { doc in
            DocumentGroupRoot(...)
        }.commands { Menus(root: root) }
        
        WindowGroup("Preset Color Maps") {
             ... .handlesExternalEvents(matching: ...) /// Allows multiple windows
        }.handlesExternalEvents(matching: ...)
        
        WindowGroup("Tutorial") {
             ...
        }.handlesExternalEvents(matching: ...)
    }
}

Stuck on wiring "New Project" replacement

enter image description here

struct NewCommands: Commands {
    var body: some Commands {
        CommandGroup(replacing: .newItem) {
            NewProjectButton()
        }
        
        CommandGroup(after: .newItem) {
            ImportersButtons()
        }
    }

    private struct NewButton: View {
        
        @Environment(\.openURL) var openURL
        
        var body: some View {
            Button("New Project") { openURL(ExternalEvents.new.url) }
                .keyboardShortcut("n", modifiers: .command)
        }
    }
}
@main
struct TheApp: App {
    
    @StateObject var root: RootStore
    
    var body: some Scene {
        DocumentGroup { ProjectDocument() } editor: { doc in
            DocumentGroupRoot(...)
                .handlesExternalEvents(...) /// Doesn't enable new doc windows
        }.commands { Menus(root: root) }
         .handlesExternalEvents(matching: ...) /// Only makes existing doc key window
        
        ...
    }
}
1

There are 1 answers

2
Ryan On

Ok, classic. Posted and then solved. The solution was just going back to the shared NSDocumentController and asking for a new document. I'll go blush in the corner.

Button("New Project") {
      NSDocumentController.shared.newDocument(nil)
}