You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS SwiftUI:用WindowGroup实现设置窗口并关联系统设置命令

用WindowGroup关联macOS系统标准设置命令的解决方案

核心思路

通过自定义系统命令组替换默认的设置命令,同时给WindowGroup设置唯一ID,确保系统的「设置」菜单选项、快捷键⌘+,都指向你的自定义设置窗口,同时保留WindowGroup带来的窗口大小调整、工具栏合并等正常功能。

步骤实现

  1. 给设置窗口的WindowGroup指定唯一ID
    先给你的设置窗口场景分配一个唯一标识,方便后续精准定位:
WindowGroup(id: "AppSettings") {
    SettingsView()
        .windowResizability(.contentSize) // 可正常调整窗口大小规则
        .toolbar {
            // 工具栏可正常使用各类placement,比如与标题栏合并的principal位置
            ToolbarItem(placement: .principal) {
                Text("应用设置")
            }
            // 其他工具栏项示例
            ToolbarItem(placement: .navigation) {
                Button("重置") { /* 你的业务逻辑 */ }
            }
        }
}
  1. 替换系统默认的Settings命令
    在App结构体中通过.commands修饰符,替换系统自带的设置命令组,让系统的设置触发逻辑指向你的WindowGroup窗口:
@main
struct YourMacApp: App {
    var body: some Scene {
        // 主窗口场景
        WindowGroup {
            MainContentView()
        }
        
        // 自定义设置窗口场景
        WindowGroup(id: "AppSettings") {
            SettingsView()
                .windowResizability(.contentSize)
                .toolbar {
                    ToolbarItem(placement: .principal) {
                        Text("应用设置")
                    }
                }
        }
        
        // 重写系统命令
        .commands {
            CommandGroup(replacing: .settings) {
                Button("设置…") {
                    // 优先激活已存在的设置窗口,避免重复创建
                    if let settingsWindow = NSApp.windows.first(where: {
                        $0.identifier?.rawValue == "AppSettings"
                    }) {
                        settingsWindow.makeKeyAndOrderFront(nil)
                    } else {
                        // 若窗口未创建,触发场景打开
                        NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
                    }
                }
                .keyboardShortcut(",", modifiers: .command) // 保留系统默认快捷键
            }
        }
    }
}
  1. 优化窗口单例行为
    为避免重复打开多个设置窗口,可在SettingsView中配置窗口关闭行为,让窗口关闭时不销毁,下次直接显示:
struct SettingsView: View {
    var body: some View {
        // 你的设置界面内容
        Text("设置页面内容")
            .onAppear {
                guard let window = NSApp.windows.first(where: {
                    $0.identifier?.rawValue == "AppSettings"
                }) else { return }
                window.isReleasedWhenClosed = false // 关闭时不释放窗口实例
                window.setFrameAutosaveName("AppSettingsFrame") // 自动保存窗口位置与大小
            }
    }
}

补充说明

  • 切换到WindowGroup后,工具栏的placement参数可正常生效,.principal、.navigation等位置的工具栏项会和标题栏合并,解决之前的分离问题。
  • .windowResizability()修饰符可正常设置窗口大小规则,比如固定内容大小、最小/最大尺寸等,无功能限制。
  • 这种方式实现的设置窗口,与原生Settings场景的用户体验一致,系统所有设置触发入口(菜单栏、快捷键、系统偏好设置里的应用设置入口)都会指向你的自定义窗口。

内容的提问来源于stack exchange,提问作者Kaven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 15:32:49