我正在构建一个单窗口应用程序,并希望使用新的Swift应用程序生命周期。
import SwiftUI
@main
struct SingleWindowApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
WindowGroup
的默认实现允许窗口的多个实例(即,如果您点击⌘N
)。我无法找到改变这种行为的修饰符。
如何将 WindowGroup 中的窗口数量限制为 1?
这应该可以做到:
import SwiftUI
@main
struct SingleWindowApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
CommandGroup(replacing: .newItem, addition: { })
}
}
}
在 Xcode 14 中,就像创建一个
Scene
一样简单,只有一个 id 为 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
每次打开一个WindowGroup对象时,都可以使用NSViewControllerRepresentable来获取该视图的NSWindow实例。
然后考虑定义一个外部对象来存储NSWindows的集合。下次打开WindowGroup对象时,如果NSWindow集合已满,则查找对应的NSWindow进行显示。例如
if windowList.isfull {
let window = windowList.getWindow()
window.makeKey()
window.orderFront(nil)
} else {
NSWorkspace.shared.open(url)
}
关于如何从WindowGroup获取NSWindow的实例,可以考虑一个开源实现: 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()
}
}
}
}