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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:36:25