You need to enable JavaScript to run this app. Swift开发中如何基于AVPlayer实现本地视频的不间断循环播放
优惠活动
大模型
产品
解决方案
定价
更多

Swift开发中如何基于AVPlayer实现本地视频的不间断循环播放

AVPlayer实现本地视频循环播放的落地方案

首先修正现有代码的两个基础问题:

  • 原代码中AVPlayer、AVPlayerLayer都是局部变量,方法执行结束后会被ARC回收,极易出现播放中途中断、异常闪退的问题,需要改为类的强引用成员变量持有。
  • 原代码无播放完成后的进度重置逻辑,AVPlayer默认播放到结尾就会停止,不会自动回到开头。

方案一:使用AVPlayerLooper(推荐,iOS 10+ 支持)

这是苹果官方提供的无缝循环播放工具,内部会自动处理播放完成的重置逻辑,没有手动重置带来的卡顿,性能最优。

实现步骤

  1. 在对应类中添加强引用的成员变量:
private var player: AVPlayer?
private var playerLayer: AVPlayerLayer?
private var playerLooper: AVPlayerLooper?
  1. 修改播放函数:
func playVideo() {
    guard let path = Bundle.main.path(forResource: "intro", ofType: "mp4") else {
        return
    }
    let url = URL(fileURLWithPath: path)
    let playerItem = AVPlayerItem(url: url)
    let player = AVPlayer(playerItem: playerItem)
    self.player = player

    // 初始化Looper,自动完成循环播放配置
    self.playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)

    // 配置播放图层
    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = self.view.bounds
    playerLayer.videoGravity = .resizeAspectFill
    self.playerLayer = playerLayer
    self.videoLayer.layer.addSublayer(playerLayer)

    player.play()
}

方案二:监听播放完成通知(兼容iOS 10以下版本)

如果需要支持更低的系统版本,可以通过监听系统通知捕获播放完成事件,手动重置播放进度。

实现步骤

  1. 在对应类中添加强引用的成员变量:
private var player: AVPlayer?
private var playerLayer: AVPlayer?
  1. 修改播放函数并添加回调逻辑:
func playVideo() {
    guard let path = Bundle.main.path(forResource: "intro", ofType: "mp4") else {
        return
    }
    let url = URL(fileURLWithPath: path)
    let player = AVPlayer(url: url)
    self.player = player

    // 注册播放完成的通知监听
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handlePlayToEnd),
        name: .AVPlayerItemDidPlayToEndTime,
        object: player.currentItem
    )

    // 配置播放图层
    let playerLayer = AVPlayerLayer(player: player)
    playerLayer.frame = self.view.bounds
    playerLayer.videoGravity = .resizeAspectFill
    self.playerLayer = playerLayer
    self.videoLayer.layer.addSublayer(playerLayer)

    player.play()
}

// 播放完成后的回调方法
@objc private func handlePlayToEnd() {
    // 重置进度到视频开头
    player?.seek(to: .zero)
    // 重新触发播放
    player?.play()
}

内存优化:页面销毁时需要移除通知监听,避免内存泄漏:

deinit {
    NotificationCenter.default.removeObserver(self)
}

通用优化点

  • 多次调用playVideo()时,先移除已存在的playerLayer,避免多层视频图层叠加显示:
// playVideo方法开头添加判断
if let oldLayer = self.playerLayer {
    oldLayer.removeFromSuperlayer()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 09:06:10