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

SwiftUI VideoPlayer嵌入VStack旋转黑屏问题排查求助

设备旋转时SwiftUI VideoPlayer变黑的问题排查与修复

你遇到的这个问题不是系统Bug,是布局和AVPlayer生命周期处理不当导致的,下面是具体问题点和修复方案:

  • AVPlayer持有方式错误
    直接在View结构体里用let player = AVPlayer()声明,虽然AVPlayer是引用类型,但SwiftUI的View是值类型,每次视图刷新(比如设备旋转)可能引发意外的状态重置。应该用@StateObject持有AVPlayer,确保它的生命周期和View绑定一致。

  • 固定高度引发布局冲突
    给VideoPlayer设置固定height:300,设备旋转后屏幕宽高比变化,固定高度会让播放器渲染区域和实际显示区域不匹配,最终导致黑屏。建议改用自适应宽高比布局。

  • 重复的ignoresSafeArea导致渲染混乱
    外层VStack已经添加了.ignoresSafeArea(),内部VideoPlayer再添加该修饰符会让旋转时的安全区计算异常,干扰视图正常渲染。


修改后的完整代码

import SwiftUI
import AVKit

struct VideoPlayerView: View {
    let videoURL: URL
    // 用@StateObject稳定持有AVPlayer
    @StateObject private var player = AVPlayer()
    
    var body: some View {
        VStack {
            VideoPlayer(player: player)
                .frame(maxWidth: .infinity)
                // 用宽高比适配不同屏幕方向
                .aspectRatio(16/9, contentMode: .fit)
                .padding()
                .background(Color.black)
                .onTapGesture {
                    player.rate = player.rate == 0.0 ? 1.0 : 0.0
                }
            
            Spacer()
        }
        .ignoresSafeArea()
        .background(Color.black)
        .onAppear {
            let audioSession = AVAudioSession.sharedInstance()
            do {
                try audioSession.setCategory(.playback, mode: .default, options: .duckOthers)
            } catch {
                NSLog("Unable to set session category to playback")
            }
            
            // 避免重复设置相同的playerItem
            guard player.currentItem?.asset != AVAsset(url: videoURL) else { return }
            let playerItem = AVPlayerItem(url: videoURL)
            player.replaceCurrentItem(with: playerItem)
        }
        .onDisappear {
            // 页面消失时清理资源
            player.pause()
            player.replaceCurrentItem(with: nil)
        }
    }
}

若使用AVPlayerViewController封装的补充说明

如果是通过UIViewControllerRepresentable封装AVPlayerViewController,需要注意:

  1. 同样用@StateObject持有AVPlayer,避免生命周期异常;
  2. 在updateUIViewController方法中不要重复创建控制器或重置player,仅更新必要状态;
  3. 确保控制器的布局适配屏幕旋转,不要硬固定尺寸。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:07:36