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

visionOS沉浸式视频应用重载问题求助:无法返回原路径

解决visionOS沉浸式视频应用窗口隐藏而非关闭的方案

一、利用ScenePhase与窗口状态管理实现隐藏逻辑

在visionOS中,无需关闭窗口,可通过控制窗口的isHidden属性实现隐藏,结合场景状态监听与视频播放事件回调,完成播放时隐藏、结束后恢复的流程。

1. SwiftUI实现示例

通过环境变量scenePhase监听场景状态,配合全屏封面展示沉浸式视频,同时控制主窗口的隐藏与恢复:

import SwiftUI
import AVKit

struct ContentView: View {
    @Environment(\.scenePhase) private var scenePhase
    @State private var isPlayingImmersive = false
    @State private var videoPlayer: AVPlayer?
    
    var body: some View {
        VStack(spacing: 20) {
            Button("启动沉浸式视频") {
                guard let videoURL = Bundle.main.url(forResource: "immersive_content", withExtension: "mov") else { return }
                videoPlayer = AVPlayer(url: videoURL)
                isPlayingImmersive = true
            }
            // 其他界面元素
        }
        .fullScreenCover(isPresented: $isPlayingImmersive) {
            // 退出沉浸式时恢复主窗口
            if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
                windowScene.windows.first?.isHidden = false
            }
        } content: {
            // 进入沉浸式前隐藏主窗口
            if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
                windowScene.windows.first?.isHidden = true
            }
            VideoPlayer(player: videoPlayer)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .onDisappear {
                    videoPlayer?.pause()
                }
        }
    }
}

2. UIKit实现示例

在UIWindowSceneDelegate中直接管理窗口状态,配合AVPlayer的播放结束通知完成窗口恢复:

import UIKit
import AVKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    private var immersivePlayerVC: AVPlayerViewController?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else { return }
        window = UIWindow(windowScene: windowScene)
        window?.rootViewController = MainViewController()
        window?.makeKeyAndVisible()
    }

    // 外部调用此方法启动沉浸式视频
    func startImmersiveVideo(with url: URL) {
        immersivePlayerVC = AVPlayerViewController()
        immersivePlayerVC?.player = AVPlayer(url: url)
        immersivePlayerVC?.player?.play()
        
        // 隐藏主窗口
        window?.isHidden = true
        
        // 监听视频结束事件
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(onVideoPlaybackEnded),
            name: .AVPlayerItemDidPlayToEndTime,
            object: immersivePlayerVC?.player?.currentItem
        )
        
        // 展示沉浸式播放器窗口
        if let playerWindow = immersivePlayerVC?.view.window {
            window?.windowScene?.addWindow(playerWindow)
            playerWindow.makeKeyAndVisible()
        }
    }

    @objc private func onVideoPlaybackEnded() {
        // 恢复主窗口显示
        window?.isHidden = false
        // 清理播放器资源
        immersivePlayerVC?.player?.pause()
        immersivePlayerVC?.dismiss(animated: true)
        immersivePlayerVC = nil
        NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: nil)
    }
}

二、关键注意事项

  • 需在Info.plist中配置后台模式(添加audio, airplay, and picture in picture权限),避免窗口隐藏后应用被系统挂起。
  • 确保视频结束事件的监听逻辑可靠,避免出现窗口无法自动恢复的情况。
  • 测试时需验证沉浸式场景与窗口状态切换的流畅性,保证视频播放体验不受影响。

三、备选方案(若窗口隐藏仍有问题)

如果窗口隐藏方案未达预期,可通过持久化保存用户路径,在应用启动时自动跳转:

// 保存当前界面标识
UserDefaults.standard.set("video_browse", forKey: "last_accessed_scene")

// 应用启动时恢复路径
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let lastScene = UserDefaults.standard.string(forKey: "last_accessed_scene") ?? "initial"
    window?.rootViewController = lastScene == "video_browse" ? VideoBrowseViewController() : InitialViewController()
    return true
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:28:15