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,需要注意:
- 同样用
@StateObject持有AVPlayer,避免生命周期异常; - 在
updateUIViewController方法中不要重复创建控制器或重置player,仅更新必要状态; - 确保控制器的布局适配屏幕旋转,不要硬固定尺寸。
内容的提问来源于stack exchange,提问作者Deepak Sharma
相关产品推荐
相关产品推荐

