Search code examples
swiftmemoryavplayer

Memory Leak with AVPlayer playing online audio streaming


I am making an app for playing podcasts. the problem is when creating an AVPlayer with URL or AVPlayer item. a memory leak happens but deinit works well with no problem.

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)
   // when comment the avplear init no memory leaks found.
    audioPlayer = AVPlayer(playerItem: playerItem)
    
    addEndPlayingObserver()
    startPlaying()
    
}

when debugging with instruments I got this

enter image description here

I tried to debug this malloc 16 bytes on Xcode but I failed on this because the object is not at any memory graph.


Solution

  • This is because setting an AVPlayerItem on an AVPlayer creates a hidden strong reference between the two, so persisting the AVPlayerItem will hang onto the AVPlayer, causing a memory leak. make share the AVPlayerItem and AVPlayer have a 1:1 relationship by creating a new AVPlayerItem when it needs to be assigned to an AVPlayer.

     guard let url = audioURL else {
        return
     }
    
     let originalAsset = AVAsset(url: url)
    
     audioPlayer = AVPlayer(playerItem: AVPlayerItem(asset: originalAsset))
    

    If the above approach doesn't help you try this on your viewDidDissapear:

     func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        self.audioPlayer?.replaceCurrentItem(with: nil)
     }