SwiftUI for macOS:如何关闭WindowGroup所有窗口并阻止重启恢复?
解决SwiftUI macOS数据驱动窗口组的持久化问题
一、直接禁用窗口组的持久化(推荐方案)
从macOS 13(Ventura)开始,WindowGroup支持通过persistence参数关闭持久化特性,从根源解决窗口重启恢复的问题——不管是正常退出还是意外崩溃,重启后该窗口组下的所有详情窗口都不会自动打开。
修改你的App.swift代码,给数据驱动的WindowGroup添加persistence: .none:
@main struct MyApp: App { @State var vm = ViewModel() var body: some Scene { WindowGroup { // 主窗口 ContentView() .environment(vm) } // 禁用窗口状态持久化 WindowGroup(for: Item.ID.self, persistence: .none) { $itemID in ItemDetails(itemID: itemID) .environment(vm) } } }
二、程序化关闭所有窗口(兼容旧系统/主动清理场景)
如果需要兼容macOS 13以下的版本,或者需要主动关闭所有详情窗口,可以借助AppKit的API实现精准清理:
1. 给窗口组设置唯一标识符
先修改App.swift中的详情窗口组,添加专属ID用于后续识别:
WindowGroup(for: Item.ID.self, id: "ItemDetailsWindow") { $itemID in ItemDetails(itemID: itemID) .environment(vm) }
2. 实现批量关闭方法
在你的ViewModel中添加遍历并关闭目标窗口的逻辑:
class ViewModel: ObservableObject { // 你的现有业务代码... func closeAllItemDetailsWindows() { NSApplication.shared.windows.forEach { window in // 通过标识符精准匹配详情窗口 if window.identifier == NSUserInterfaceItemIdentifier("ItemDetailsWindow") { window.close() } } } }
3. 触发清理操作
- 启动时自动清理:在主视图的
onAppear中调用,处理意外退出后的遗留窗口(注意:此场景下窗口会短暂显示再关闭)
struct ContentView: View { @Environment(ViewModel.self) private var vm @Environment(\.openWindow) private var openWindow var body: some View { ForEach(vm.items) { item in Button(item.name) { openWindow(value: item.id) } } .onAppear { vm.closeAllItemDetailsWindows() } } }
- 手动触发:添加按钮让用户主动关闭所有详情窗口
// 在ContentView中添加按钮 Button("关闭所有详情窗口") { vm.closeAllItemDetailsWindows() }
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

