SwiftUI WindowGroup:如何限制窗口数量?

问题描述 投票:0回答:5

我正在构建一个窗口应用程序,并希望使用新的Swift应用程序生命周期

import SwiftUI

@main
struct SingleWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

WindowGroup
的默认实现允许窗口的多个实例(即,如果您点击
⌘N
)。我无法找到改变这种行为的修饰符。

如何将 WindowGroup 中的窗口数量限制为 1?

swift macos swiftui swiftui-windowgroup windowgroup
5个回答
8
投票

这应该可以做到:

import SwiftUI

@main
struct SingleWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commands {
            CommandGroup(replacing: .newItem, addition: { })
        }
    }
}

6
投票

在 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


3
投票

当我面临同样的问题,但在 iPad 上,命令修饰符没有效果时,我发现了这一点:Info.plist 中有一个“应用程序场景清单”

UIApplicationSceneManifest
属性,它是一个字典,并且作为子属性“Enable”多个窗口”
UIApplicationSupportsMultipleScenes
默认设置为
YES
。将此选项设置为
NO
可达到所需的效果:)


2
投票

每次打开一个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


1
投票

以下是如何使用普通 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()
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.