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

SwiftUI Mac如何通过菜单命令创建单实例窗口?

SwiftUI 实现单实例日志窗口(懒加载/启动隐藏)

理想方案:懒加载创建,关闭即销毁,重新打开重建

直接通过条件渲染控制窗口的存在,配合菜单命令触发状态切换,关闭窗口时自动重置状态,实现完全的懒加载和销毁逻辑:

@main
struct YourApp: App {
    // 控制日志窗口的创建/销毁状态
    @State private var shouldShowLogWindow = false

    var body: some Scene {
        // 主窗口
        WindowGroup {
            MainView()
        }
        .commands {
            CommandGroup(after: .windowArrangement) {
                Button(shouldShowLogWindow ? "隐藏日志窗口" : "显示日志窗口") {
                    shouldShowLogWindow.toggle()
                }
            }
        }

        // 条件渲染日志窗口:仅当shouldShowLogWindow为true时才创建
        if shouldShowLogWindow {
            Window("日志", id: "unique-log-window") {
                LogView() // 你的日志展示视图
                    .onDisappear {
                        // 窗口关闭时自动重置状态,下次打开会重新创建
                        shouldShowLogWindow = false
                    }
            }
            .windowResizability(.contentSize) // 根据内容调整窗口大小
        }
    }
}

逻辑说明

  • 启动时shouldShowLogWindow为false,日志窗口不会被创建,完全懒加载;
  • 点击菜单命令切换状态为true,SwiftUI自动创建并显示日志窗口;
  • 手动关闭窗口时,onDisappear触发,将shouldShowLogWindow设为false,窗口被销毁;
  • 再次点击菜单命令,状态变回true,重新创建新的日志窗口。

退而求其次:启动时隐藏,菜单命令控制显示/隐藏

如果需要窗口始终存在但启动时隐藏,不要用.hidden()修饰符(会永久隐藏),而是通过NSWindow的API手动控制窗口的显示状态:

@main
struct YourApp: App {
    @State private var logWindowVisible = false
    // 存储日志窗口的引用,用于后续控制显示隐藏
    private var logWindow: NSWindow?

    var body: some Scene {
        WindowGroup {
            MainView()
        }
        .commands {
            CommandGroup(after: .windowArrangement) {
                Button(logWindowVisible ? "隐藏日志窗口" : "显示日志窗口") {
                    guard let window = logWindow else { return }
                    if logWindowVisible {
                        window.orderOut(nil) // 隐藏窗口
                    } else {
                        window.orderFront(nil) // 显示窗口
                        NSApp.activate(ignoringOtherApps: true) // 激活应用窗口
                    }
                    logWindowVisible.toggle()
                }
            }
        }

        // 启动时创建但隐藏的日志窗口
        Window("日志", id: "unique-log-window") {
            LogView()
                .onAppear {
                    // 通过窗口ID匹配获取当前日志窗口的引用
                    logWindow = NSApp.windows.first {
                        $0.identifier == NSUserInterfaceItemIdentifier("unique-log-window")
                    }
                    // 启动时立即隐藏窗口
                    logWindow?.orderOut(nil)
                    logWindowVisible = false
                }
        }
        .windowResizability(.contentSize)
    }
}

逻辑说明

  • 启动时窗口会被创建,但onAppear中调用orderOut(nil)将其隐藏;
  • 菜单命令通过操作NSWindow的orderFront/orderOut方法控制显示/隐藏;
  • 用窗口ID精准匹配目标窗口,避免误操作其他应用窗口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:22:42