【问题标题】:macOS SwiftUI: Instantiate new non-document window in document appmacOS SwiftUI:在文档应用程序中实例化新的非文档窗口
【发布时间】:2021-05-03 03:38:48
【问题描述】:

有没有一种纯 SwiftUI 的方式来打开一个新窗口?我有一个排序工作的基于文档的应用程序,其应用程序如下所示:

@main struct MyApp: App
{
    var
    body: some Scene {
        DocumentGroup(newDocument: ProjectDocument.init) { inGroup in
            ProjectWindowContentView(document: inGroup.document)
                .frame(minWidth: 301.0, minHeight: 100.0)
                .onReceive(self.addTerrainGeneratorLayerCommand) { _ in
                    inGroup.document.addTerrainGeneratorLayer()
                }
        }
        .commands {
            ...
        }
    }
    ...
}

现在我想添加一个菜单命令来在它自己的窗口中实例化一个小的独立实用工具。到目前为止,我在网上看到的任何讨论实际上都涉及制作一个新的NSWindow,并将NSHostingView 作为其内容视图。这似乎不是很 SwiftUI 风格,考虑到他们最近添加的 DocumentGroupWindowGroup 似乎是一个很大的疏忽。

我尝试在应用的场景中添加WindowGroup,但如果我注释掉DocumentGroup,它只会显示我的窗口。

【问题讨论】:

    标签: swiftui macos-big-sur


    【解决方案1】:

    我们需要一个WindowGroup 作为窗口,所以第一步/简单的步骤就是添加它,就像

    (使用 Xcode 12.5 / macOS 11.3 创建的 Demo,基于 Document App 模板)

    struct PlayDocumentXApp: App {
        var body: some Scene {
            DocumentGroup(newDocument: PlayDocumentXDocument()) { file in
                ContentView(document: file.$document)
            }
            WindowGroup("Tools") {
                Text("This is tool window")
                    .frame(width: 200, height: 400)
            }
        }
    }
    

    我们可以通过File > New 菜单获得它

    如果我们想从其他地方以编程方式创建/显示它,比如通过命令,我们可以使用基于 URL 的方法,例如

    struct PlayDocumentXApp: App {
        var body: some Scene {
            DocumentGroup(newDocument: PlayDocumentXDocument()) { file in
                ContentView(document: file.$document)
            }
            .commands {
                CommandMenu("Test") {
                    Button("Show Tools") {
                        NSWorkspace.shared.open(URL(string: "myTools://my")!)
                    }
                }
            }
            WindowGroup("Tools") {
                Text("This is tool window")
                    .frame(width: 200, height: 400)
                    .handlesExternalEvents(preferring: Set(arrayLiteral: "myTools://my"), allowing: Set(arrayLiteral: "myTools://my"))
            }
        }
    }
    

    【讨论】:

    • 我没有意识到它在 File->New 中粘贴了一个菜单项。现在就可以了。您描述的基于 URL 的方法确实似乎是一种解决方法,但我想它有效。
    • 另外,感谢您出色而彻底的回答!
    【解决方案2】:

    从之前的优秀回答,我来到了这个sn-p。

    • 它显示了如何在Window 菜单中添加命令
    • 语法有点短(handleExternalEvents(matching:))
    WindowGroup("Tools", id: "tools") {
        Text("This is tool window")
    }
    .commands {
        CommandGroup(after: CommandGroupPlacement.windowList) {
            Button(action: {
                NSWorkspace.shared.open(URL(string: "myTools://my")!)
            }, label: {
                Text("Tool Window")
            })
        }
    }
    .handlesExternalEvents(matching: ["myTools://my"])
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-25
      • 2021-10-26
      • 2020-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多