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

如何通过菜单栏按钮实现SwiftUI应用的窗口显示控制?

纯SwiftUI解决方案

问题根源

原代码错误使用@Binding管理窗口显示状态——@Binding需要绑定外部已有状态,此处应使用@State(或@AppStorage做持久化)维护App内部的窗口显示标记,同时Scene层级的条件渲染需配合正确的状态管理逻辑。

修正后的最优代码

import SwiftUI

@main
struct TestWindowApp: App {
    // 用@State维护窗口显示状态,初始为隐藏
    @State private var showWindow = false

    var body: some Scene {
        MenuBarExtra {
            Button("Show window") {
                showWindow = true
            }
            // 新增隐藏按钮,让用户可主动关闭窗口
            Button("Hide window") {
                showWindow = false
            }
        } label: {
            Text(">_<")
        }

        // 条件渲染Window:状态为true时创建窗口,false时自动销毁窗口
        if showWindow {
            Window("Window", id: "main") {
                Text("Hello, SwiftUI!")
                    .padding()
                    // 可选:窗口关闭时同步状态
                    .onDisappear {
                        showWindow = false
                    }
            }
            // 可选:设置窗口固定尺寸+居中显示
            .windowResizability(.contentSize)
            .defaultPosition(.center)
        }
    }
}

代码说明

  • 替换@Binding为@State private var showWindow = false,正确管理App内部状态
  • 条件渲染Window:状态为true时创建窗口,false时窗口自动销毁,彻底避免空窗口问题
  • 新增隐藏按钮或onDisappear回调,保证状态与窗口显示状态同步
  • 通过windowResizability和defaultPosition可自定义窗口行为,优化用户体验

可选:WindowGroup兼容方案

若因需求必须使用WindowGroup,可通过以下方式避免空窗口:

import SwiftUI

@main
struct TestWindowApp: App {
    @State private var showWindow = false

    var body: some Scene {
        MenuBarExtra {
            Button("Show window") {
                showWindow = true
                // 激活并显示指定ID的WindowGroup窗口
                NSApp.windows.first(where: { $0.identifier?.rawValue == "main-window" })?.makeKeyAndOrderFront(nil)
            }
        } label: {
            Text(">_<")
        }

        WindowGroup(id: "main-window") {
            if showWindow {
                Text("Hello, SwiftUI!")
                    .padding()
                    .onDisappear {
                        showWindow = false
                    }
            } else {
                // 空视图配合隐藏标题栏,消除空窗口视觉干扰
                Color.clear
                    .windowStyle(.hiddenTitleBar)
            }
        }
        .windowResizability(.contentSize)
    }
}

此方案复杂度更高,优先推荐第一种直接条件渲染Window的实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:41:15