如何为SwiftUI macOS应用添加可创建多实例窗口的File菜单项?
在SwiftUI macOS应用中实现多实例功能窗口及自定义菜单项
核心思路
要实现多实例窗口,必须用WindowGroup而非Window——Window是单实例结构体,而WindowGroup天生支持创建多个独立窗口实例。我们给每个功能(Wordle、Anagrams、Crosswords)分别定义专属的WindowGroup,再通过自定义菜单项触发打开对应窗口组的新实例。
具体实现步骤
1. 定义多实例窗口组
在你的App结构体中,针对macOS平台单独声明每个功能的WindowGroup,iOS平台保留原有的TabView结构:
@main struct WordPuzzleApp: App { var body: some Scene { #if os(macOS) // Wordle多实例窗口组 WindowGroup(id: "wordle-window") { WordleView() .frame(minWidth: 400, minHeight: 600) } .windowStyle(.titleBar) // Anagrams多实例窗口组 WindowGroup(id: "anagrams-window") { AnagramsView() .frame(minWidth: 400, minHeight: 600) } .windowStyle(.titleBar) // Crosswords多实例窗口组 WindowGroup(id: "crosswords-window") { CrosswordsView() .frame(minWidth: 600, minHeight: 800) } .windowStyle(.titleBar) #else // iOS平台保留TabView单实例结构 WindowGroup { TabView { WordleView() .tabItem { Label("Wordle", systemImage: "square.grid.2x2") } AnagramsView() .tabItem { Label("Anagrams", systemImage: "textformat") } CrosswordsView() .tabItem { Label("Crosswords", systemImage: "square.and.pencil") } } } #endif } }
2. 添加自定义File菜单项
在App结构体中添加commands修饰符,给macOS平台的File菜单新增三个自定义选项,每个选项通过openWindow(id:)触发对应窗口组的新实例:
@main struct WordPuzzleApp: App { var body: some Scene { // 上面的WindowGroup/TabView代码... #if os(macOS) CommandGroup(after: .newItem) { Button("New Wordle Window") { openWindow(id: "wordle-window") } .keyboardShortcut("W", modifiers: [.command, .shift]) Button("New Anagrams Window") { openWindow(id: "anagrams-window") } .keyboardShortcut("A", modifiers: [.command, .shift]) Button("New Crosswords Window") { openWindow(id: "crosswords-window") } .keyboardShortcut("C", modifiers: [.command, .shift]) } #endif } }
关键细节说明
WindowGroup的id是核心标识:调用openWindow(id:)时,系统会根据这个ID找到对应的窗口组,并创建一个全新的实例。- 自定义快捷键:给每个菜单项添加快捷键可以提升用户体验,比如
Cmd+Shift+W对应Wordle窗口,贴合macOS操作习惯。 - 窗口样式与尺寸:可以给每个
WindowGroup设置windowStyle和初始尺寸,让不同功能的窗口更贴合需求。
验证效果
运行macOS应用后,打开File菜单就能看到新增的三个选项,每次点击都会弹出对应功能的全新窗口,所有窗口独立运行、互不干扰;iOS平台则保持原有的TabView切换逻辑。
内容的提问来源于stack exchange,提问作者Duncan C
相关产品推荐
相关产品推荐

