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

SwiftUI macOS应用如何默认隐藏所有窗口?

问题描述

开发纯SwiftUI菜单栏应用时遇到以下问题:

  • SwiftUI中定义Window或WindowGroup时,应用启动总会默认打开至少一个窗口
  • 不支持直接对Window使用条件渲染(如if x { Window() })
  • 需求:根据用户默认设置(showIntroduction)决定是否显示引导窗口,另一个窗口通过菜单栏手动触发打开

当前代码如下:

import SwiftUI

@main
struct ExampleApp: App {
    @Environment(\.openWindow) var openWindow
    @AppStorage("showIntroduction") private var showIntroduction = true

    init() {
        if showIntroduction {
            print("Show introduction")
            openWindow(id: "introduction")
        }
    }

    var body: some Scene {
        // How to hide this window by default?
        Window("Intro", id: "introduction") {
            WelcomeView()
        }
            .windowStyle(.hiddenTitleBar)
        Settings {
            SettingsView()
        }
        MenuBarExtra {
            MenuBarView()
        } label: {
            Text("Test")
        }
    }
}

尝试过用.hidden()修饰视图,但该修饰符不支持Window/WindowGroup;若隐藏视图被Window包裹,会出现空窗口。

请问能否通过纯SwiftUI实现需求,还是必须用编程方式创建NSWindow来实现默认不打开窗口?

解决方案

可以通过纯SwiftUI实现,无需依赖NSWindow,核心是利用macOS 13+(Ventura)引入的.defaultPresentationStyle(.hidden)修饰符,让Window默认不显示,仅通过openWindow环境变量按需唤起。

调整后的代码

import SwiftUI

@main
struct ExampleApp: App {
    @Environment(\.openWindow) var openWindow
    @AppStorage("showIntroduction") private var showIntroduction = true

    init() {
        // 仅当用户设置为true时,主动唤起引导窗口
        if showIntroduction {
            print("Show introduction")
            openWindow(id: "introduction")
        }
    }

    var body: some Scene {
        // 设置引导窗口默认隐藏,仅通过openWindow触发显示
        Window("Intro", id: "introduction") {
            WelcomeView()
                .onDisappear {
                    // 引导窗口关闭后,标记为已展示
                    showIntroduction = false
                }
        }
        .windowStyle(.hiddenTitleBar)
        .defaultPresentationStyle(.hidden) // 关键:默认不渲染窗口

        // 若需要手动打开的其他窗口,同样设置默认隐藏
        Window("Main Window", id: "main") {
            MainContentView()
        }
        .defaultPresentationStyle(.hidden)

        Settings {
            SettingsView()
        }

        MenuBarExtra {
            MenuBarView()
        } label: {
            Text("Test")
        }
    }
}

菜单栏触发打开窗口的实现(MenuBarView示例)

struct MenuBarView: View {
    @Environment(\.openWindow) var openWindow
    @Environment(\.dismissWindow) var dismissWindow

    var body: some View {
        Button("打开主窗口") {
            openWindow(id: "main")
        }
        Button("关闭主窗口") {
            dismissWindow(id: "main")
        }
        Divider()
        Button("退出") {
            NSApplication.shared.terminate(nil)
        }
    }
}

说明

  • .defaultPresentationStyle(.hidden)会让Window在应用启动时默认不显示,只有通过openWindow(id:)主动调用才会弹出窗口
  • 该方案要求系统版本为macOS 13.0+(Ventura)及以上,若需兼容更低版本,则需要通过AppKit的NSWindow手动创建管理窗口
  • 引导窗口关闭时,通过onDisappear将showIntroduction设为false,避免下次启动重复显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:22:54