SwiftUI WindowGroup: как ограничить количество окон?
Я создаю приложение с одним окном и хочу использовать новый жизненный цикл приложения Swift.
import SwiftUI
@main
struct SingleWindowApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Реализация по умолчанию
WindowGroup
позволяет несколько экземпляров окна (т.е. если вы нажмете
⌘N
). Мне не удалось найти модификатор, изменяющий это поведение.
Как мне ограничить количество окон в WindowGroup одним?
5 ответов
Это должно сделать это:
import SwiftUI
@main
struct SingleWindowApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}.commands {
CommandGroup(replacing: .newItem, addition: { })
}
}
}
В Xcode 14 это так же просто, как создатьScene
только сWindow
с идентификаторомmain
.
Это открывает окно и не включаетFile -> New
пункт меню.
var body: some Scene {
Window("My Single Window", id: "main") {
ContentView()
}
}
Соответствующая документация здесь: https://developer.apple.com/documentation/swiftui/window#Use-a-window-as-the-main-scene.
Поскольку я столкнулся с той же проблемой, но на iPad, где модификатор команды не действует, я обнаружил следующее: «Манифест сцены приложения»
UIApplicationSceneManifest
свойство в вашем Info.plist, которое является словарем и дочерним элементом «Включить несколько окон»
UIApplicationSupportsMultipleScenes
который установлен на
YES
по умолчанию. Устанавливает этот параметр на
NO
дает нужный эффект :)
Каждый раз, когда вы открываете объект WindowGroup, вы можете использовать NSViewControllerRepresentable для получения экземпляра представления NSWindow.
Затем рассмотрите возможность определения внешнего объекта для хранения коллекции NSWindows. В следующий раз, когда вы откроете объект WindowGroup, если коллекция NSWindow заполнена, найдите соответствующий NSWindow для отображения. например
if windowList.isfull {
let window = windowList.getWindow()
window.makeKey()
window.orderFront(nil)
} else {
NSWorkspace.shared.open(url)
}
О том, как получить экземпляр NSWindow из WindowGroup, вы можете рассмотреть реализацию с открытым исходным кодом:https://github.com/happycodelucky/SwiftUIWindowBinder .
Вот как вы можете использовать обычный код SwiftUI, чтобы отключить «Файл -> Новое окно», когда главное окно открыто, и включить «Файл -> Новое окно», когда главное окно закрыто.
В этом коде, вероятно, есть некоторые крайние случаи, которые можно было бы доработать, но он работает.
import SwiftUI
@main
struct MyApp: App {
@State var isMainWindowOpen = false
var body: some Scene {
WindowGroup {
ContentView()
.onAppear {
print("Main window appeared")
self.isMainWindowOpen = true
}
.onDisappear {
print("Main window disappeared")
self.isMainWindowOpen = false
}
}.commands {
if isMainWindowOpen {
CommandGroup(replacing: .newItem) {
Button("New Window", action: {})
.disabled(true)
// This is the same keyboard shortcut as the default New Window option.
// We're just doing this so that our disabled dummy option shows
// the same shortcut visually.
.keyboardShortcut(KeyboardShortcut("n", modifiers: [.command]))
}
} else {
// By doing nothing here, we let the default
// "File -> New Window" item display and handle input.
EmptyCommands()
}
}
}
}