使用AVPlayerViewController后台播放后返回应用视频自动关闭如何解决
问题根因
该问题核心由两个原因导致:
- 未实现
AVPlayerViewControllerDelegate的全屏控制回调,系统默认会在用户点击退出全屏按钮时自动dismiss当前弹出的播放器实例 - 每次点击播放都新建播放器实例,且没有做播放进度持久化,实例销毁后进度自然丢失,同时你原来的音频会话使用了自定义初始化的实例而非系统单例,本身配置也不生效
修复方案
步骤1:改造自定义VideoPlayer类,实现代理和状态保存
import AVKit import AVFoundation class VideoPlayer: AVPlayerViewController, AVPlayerViewControllerDelegate { // 对外暴露保存的播放进度,外部持有实例时可直接复用 var lastPlayTime: CMTime = .zero init(url: URL) { super.init(nibName: nil, bundle: nil) // 设置代理接管全屏控制逻辑 delegate = self player = AVPlayer(url: url) // 必须使用音频会话单例配置,自定义初始化的实例无效 let audio = AVAudioSession.sharedInstance() do { try audio.setCategory(.playback, mode: .moviePlayback) try audio.setActive(true) } catch { print("音频会话配置失败: \(error.localizedDescription)") } // 监听播放进度实时保存 player?.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 1), queue: .main) { [weak self] time in self?.lastPlayTime = time } // 禁止下拉手势关闭播放器,可选配置 isModalInPresentation = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 接管退出全屏逻辑,禁止系统自动dismiss播放器 func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { coordinator.animate(alongsideTransition: nil) { _ in // 如果你需要退出全屏时主动关闭播放器才打开下面的注释,否则留空即可 // self.dismiss(animated: true) } } }
步骤2:修改唤起逻辑,全局持有播放器实例复用
不要每次点击播放都新建实例,在当前控制器中声明属性持有播放器,复用已有的实例恢复播放:
// 在当前控制器类中声明属性,持有播放器实例避免被销毁 var videoPlayer: VideoPlayer? // 修改按钮点击的唤起逻辑 imageViewButton.addAction(UIAction() { [weak self] _ in guard let self = self, let movieUrl = post.movie else { return } if let existPlayer = self.videoPlayer { // 已有实例直接恢复上次播放进度后弹出 existPlayer.player?.seek(to: existPlayer.lastPlayTime, completionHandler: { _ in existPlayer.player?.play() }) self.vc?.present(existPlayer, animated: true) } else { // 首次播放新建实例并保存 let newPlayer = VideoPlayer(url: movieUrl) self.videoPlayer = newPlayer self.vc?.present(newPlayer, animated: true) } }, for: .touchUpInside)
可选优化:后台切回前台自动续播
如果需要应用从后台切回前台时自动恢复播放,可以在VideoPlayer的init方法中添加通知监听:
// 放在init方法中 NotificationCenter.default.addObserver(self, selector: #selector(resumePlayWhenEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil) // 实现回调方法 @objc private func resumePlayWhenEnterForeground() { player?.play() }
内容的提问来源于stack exchange,提问作者Trev347
相关产品推荐
相关产品推荐

