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

如何指定visionOS应用启动时显示的WindowGroup?

在visionOS SwiftUI应用中指定重启后默认打开的WindowGroup

问题描述

我在开发visionOS SwiftUI应用时使用了多个WindowGroup,遇到了窗口恢复的问题:当关闭所有窗口后重启应用,系统会默认打开最后关闭的那个WindowGroup,但我希望每次重启都默认打开第一个(根)WindowGroup。

复现代码如下:

主App代码:

import SwiftUI

@main
struct demoApp: App {
    var body: some Scene {
        WindowGroup {
            FirstView()
        }

        WindowGroup(id: "second") {
            SecondView()
        }
    }
}

FirstView:

import SwiftUI

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

    var body: some View {
        VStack {
            Text("First window group")
            Button("Open second window group") {
                openWindow(id: "second")
            }
        }
    }
}

SecondView:

import SwiftUI

struct SecondView: View {
    var body: some View {
        Text("Second window group")
    }
}

操作步骤:

  1. 应用启动显示第一个WindowGroup;
  2. 点击按钮打开第二个WindowGroup;
  3. 关闭第一个窗口,再关闭第二个窗口;
  4. 重启应用,发现打开的是第二个WindowGroup,不符合预期。

解决方案

要覆盖系统默认的窗口恢复行为,可通过以下两种方式实现:

方案一:使用onLaunch强制打开主窗口

visionOS支持onLaunch修饰符,可在应用启动时直接指定要打开的窗口,覆盖系统自动恢复逻辑。需给主WindowGroup设置明确ID,启动时调用openWindow打开它,同时关闭可能被恢复的其他窗口。

修改后的App代码:

import SwiftUI

@main
struct demoApp: App {
    @Environment(\.openWindow) private var openWindow
    @Environment(\.dismissWindow) private var dismissWindow
    
    var body: some Scene {
        // 给主WindowGroup设置唯一ID
        WindowGroup(id: "main") {
            FirstView()
        }

        WindowGroup(id: "second") {
            SecondView()
        }
        .onLaunch {
            // 关闭系统可能恢复的第二个窗口
            dismissWindow(id: "second")
            // 强制打开主窗口
            openWindow(id: "main")
        }
    }
}

方案二:监听场景状态,确保主窗口存在

通过监听scenePhase,当应用进入活跃状态时,检查主窗口是否存在,若不存在则打开它。这种方式可处理应用从后台唤醒等场景,覆盖范围更广。

修改后的App代码:

import SwiftUI

@main
struct demoApp: App {
    @Environment(\.openWindow) private var openWindow
    @Environment(\.scenePhase) private var scenePhase
    
    var body: some Scene {
        WindowGroup(id: "main") {
            FirstView()
        }

        WindowGroup(id: "second") {
            SecondView()
        }
        .onChange(of: scenePhase) { newPhase in
            guard newPhase == .active else { return }
            
            // 检查当前是否存在主窗口
            let hasMainWindow = UIApplication.shared.connectedScenes.contains { scene in
                guard let windowScene = scene as? UIWindowScene else { return false }
                return windowScene.session.configuration.sceneIdentifier == "main"
            }
            
            if !hasMainWindow {
                openWindow(id: "main")
            }
        }
    }
}

说明:

  • 两种方案都需要给主WindowGroup设置明确ID,确保能精准控制目标窗口;
  • 方案一适合仅需在启动时强制打开主窗口的场景,方案二更灵活,可覆盖应用后台恢复等场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:40:37