#swiftui #macos-big-sur
Вопрос:
Есть ли чисто быстрый способ открыть новое окно? У меня есть приложение на основе рабочего документа, приложение которого выглядит так:
@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
содержанием. Это кажется не очень быстрым, и, учитывая их недавние дополнения DocumentGroup
и WindowGroup
, похоже, довольно большую оплошность.
Я попытался вставить a WindowGroup
в сцену приложения, но оно показывает мое окно только в том случае, если я закомментирую DocumentGroup
.
Ответ №1:
Нам нужно WindowGroup
окно для окна, поэтому первый/простой шаг-просто добавить его, например
(Демонстрационная версия, созданная с помощью Xcode 12.5 / macOS 11.3, на основе шаблона приложения для документов)
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"))
}
}
}
Комментарии:
1. Я не понимал, что он вставляет для этого пункт меню в Файл->Создать. На данный момент этого достаточно. Описанный вами подход на основе URL-адресов, безусловно, кажется обходным путем, но я думаю, что он работает.
2. Кроме того, спасибо за отличный и обстоятельный ответ!
Ответ №2:
Из предыдущего отличного ответа я пришел к этому фрагменту.
- В нем показано, как добавить команду в
Window
меню - Синтаксис немного короче ( handleExternalEvents(соответствие:) )
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"])