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

使用AVPlayer播放在线音频流时出现内存泄漏问题

播客应用AVPlayer内存泄漏问题排查与解决

问题描述

开发播客播放应用时,通过URL或AVPlayerItem创建AVPlayer会出现内存泄漏,但对象的deinit方法可正常执行且无异常。相关代码如下:

weak var presenter: AudioPlayerUpdaterProtocol?
private var audioSession: AVAudioSession?
private var audioPlayer: AVPlayer?
private var audioURL: URL?
private var playbackTimeUpdater: Timer?

deinit {
    self.audioSession = nil
    self.audioURL = nil
    self.audioPlayer = nil
    self.playbackTimeUpdater?.invalidate()
    removeEndPlayingObserver()
    print("deinit audio")
}

private func setupAudioPlayer(){
    
    guard let url = audioURL else {
        return
    }
    
    let playerItem = AVPlayerItem(url: url)
    // 注释掉AVPlayer初始化时无内存泄漏
    audioPlayer = AVPlayer(playerItem: playerItem)
    
    addEndPlayingObserver()
    startPlaying()
    
}

使用Instruments调试发现存在16字节的malloc内存泄漏,但在Xcode内存图中无法找到对应泄漏对象。

排查与解决建议

  • 确保观察者完全移除:检查addEndPlayingObserver方法中,是否给AVPlayer或AVPlayerItem添加了KVO通知(如status、playbackBufferEmpty等),必须在removeEndPlayingObserver里彻底移除所有关联的观察者,遗漏的KVO会导致内存残留。

  • 主动释放AVPlayerItem资源:在销毁AVPlayer前,先清空其持有的playerItem,再置空AVPlayer。修改deinit方法:

deinit {
    // 先清空playerItem,释放关联资源
    audioPlayer?.replaceCurrentItem(with: nil)
    audioPlayer = nil
    
    playbackTimeUpdater?.invalidate()
    playbackTimeUpdater = nil
    
    removeEndPlayingObserver()
    
    // 停用并清理音频会话
    do {
        try audioSession?.setActive(false, options: .notifyOthersOnDeactivation)
    } catch {
        print("音频会话停用失败: \(error)")
    }
    audioSession = nil
    
    audioURL = nil
    print("deinit audio")
}
  • 彻底清理Timer:调用invalidate后必须将Timer实例置为nil,避免因Timer的弱引用残留导致微小泄漏。

  • 排查系统框架已知问题:部分iOS版本中AVPlayer存在已知的微小内存泄漏(如你遇到的16字节),如果上述操作后泄漏仍存在且量级极小、不影响应用稳定性,可判定为系统层面问题,无需过度关注。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:25:16