Swift iOS:AVPlayer视频从后台返回后冻结/暂停问题求助
解决AVPlayer从后台返回后冻结的问题
我明白你遇到的困扰——登录页的循环视频在后台停留一段时间后回到前台就卡住了,这确实是iOS中AVPlayer在后台状态下的常见行为,但我们可以通过调整应用状态监听逻辑来修复它。
先看你当前代码的核心问题:你给UIApplicationWillResignActive通知绑定了player.currentItem作为监听对象,这根本无法触发正确的应用后台状态回调,而且你完全缺少了应用回到前台时的视频恢复逻辑。
下面是完整的修复方案:
步骤1:调整通知监听策略
我们需要监听两个关键的应用状态通知:
UIApplicationWillResignActive:应用即将进入后台时,暂停视频(可选,但能减少不必要的资源消耗)UIApplicationDidBecomeActive:应用回到前台时,重置并恢复视频播放
步骤2:更新代码实现
替换你的代码为以下版本:
import AVKit class LoginViewController: UIViewController { var player: AVPlayer! var playerLayer: AVPlayerLayer! override func viewDidLoad() { super.viewDidLoad() configurePlayer() setupAppStateObservers() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // 移除通知监听,避免内存泄漏 NotificationCenter.default.removeObserver(self) } @objc fileprivate func configurePlayer(){ guard let url = Bundle.main.url(forResource: "myVideo", withExtension: ".mov") else { print("视频文件不存在,请检查文件名和路径") return } player = AVPlayer(url: url) playerLayer = AVPlayerLayer(player: player) playerLayer.videoGravity = .resizeAspectFill playerLayer.frame = view.layer.bounds player.actionAtItemEnd = .none view.layer.insertSublayer(playerLayer, at: 0) // 监听视频播放结束,实现循环逻辑 NotificationCenter.default.addObserver(self, selector: #selector(playerItemReachedEnd), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem) player.play() } @objc fileprivate func playerItemReachedEnd(){ player.seek(to: .zero) player.play() // 显式调用play,避免某些场景下seek后不自动播放 } private func setupAppStateObservers(){ // 应用即将进入后台时暂停视频 NotificationCenter.default.addObserver(self, selector: #selector(handleAppResignActive), name: UIApplication.willResignActiveNotification, object: nil) // 应用回到前台时恢复视频播放 NotificationCenter.default.addObserver(self, selector: #selector(handleAppBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) } @objc private func handleAppResignActive(){ player.pause() } @objc private func handleAppBecomeActive(){ // 重置播放位置到开头并播放,彻底解决冻结问题 player.seek(to: .zero) player.play() } }
关键修复点说明
- 正确的通知监听对象:监听应用状态通知时,
object参数传nil,这样才能接收到整个应用的状态变化通知,而不是错误地绑定到player.currentItem。 - 前台强制恢复逻辑:在
handleAppBecomeActive中,我们先调用seek(to: .zero)再调用play()——后台回来后AVPlayer的播放状态可能异常,重置位置后再播放能让视频重新渲染,彻底解决冻结问题。 - 内存泄漏防护:在
viewWillDisappear中移除所有通知监听,避免控制器被通知中心持有导致内存泄漏。 - 安全的资源获取:添加
guard let判断视频文件是否存在,避免强制解包引发崩溃。
这样修改后,你的视频在应用从后台返回时就能正常循环播放了。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

