macOS SwiftUI:在文档应用程序中实例化新的非文档 window
macOS SwiftUI: Instantiate new non-document window in document app
是否有打开新 window 的纯 SwiftUI 方式?我有一个基于文档的 sorta-working 应用程序,其应用程序如下所示:
@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 {
...
}
}
...
}
现在我想添加一个菜单命令来在它自己的 window 中实例化一个小的独立实用工具。到目前为止,我在网上看到的任何讨论实际上都涉及制作一个新的 NSWindow
并将 NSHostingView
作为其内容视图。这似乎不太像 SwiftUI,考虑到他们最近添加的 DocumentGroup
和 WindowGroup
似乎是一个很大的疏忽。
我尝试在应用程序的场景中放置一个 WindowGroup
,但如果我注释掉 DocumentGroup
,它只会显示我的 window。
我们需要 WindowGroup
作为 window,所以 first/simple 步骤只是添加它,比如
(使用 Xcode 12.5 / macOS 11.3 创建的演示,基于 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
菜单获得它
如果我们想从其他地方以编程方式create/show它,比如通过命令,我们可以使用基于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"))
}
}
}
根据之前的精彩回答,我来到了这个片段。
- 显示如何在
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"])
是否有打开新 window 的纯 SwiftUI 方式?我有一个基于文档的 sorta-working 应用程序,其应用程序如下所示:
@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 {
...
}
}
...
}
现在我想添加一个菜单命令来在它自己的 window 中实例化一个小的独立实用工具。到目前为止,我在网上看到的任何讨论实际上都涉及制作一个新的 NSWindow
并将 NSHostingView
作为其内容视图。这似乎不太像 SwiftUI,考虑到他们最近添加的 DocumentGroup
和 WindowGroup
似乎是一个很大的疏忽。
我尝试在应用程序的场景中放置一个 WindowGroup
,但如果我注释掉 DocumentGroup
,它只会显示我的 window。
我们需要 WindowGroup
作为 window,所以 first/simple 步骤只是添加它,比如
(使用 Xcode 12.5 / macOS 11.3 创建的演示,基于 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
菜单获得它
如果我们想从其他地方以编程方式create/show它,比如通过命令,我们可以使用基于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"))
}
}
}
根据之前的精彩回答,我来到了这个片段。
- 显示如何在
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"])