Impossible to stop AVPlayer
Asked Answered
L

3

42

I am currently testing the use of AVPlayer with audio streaming url, using Swift. There are play() and pause() methods, but the problem is that, pausing only, the stream remains cached in the device.

Here is my test code :

import UIKit
import AVFoundation

class ViewController: UIViewController {

    let player = AVPlayer(URL: NSURL(string: "http://streaming.radio.rtl.fr/rtl-1-48-192")!)

    @IBOutlet weak var btnPlay: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()            
    }

    @IBAction func btnPress(sender: AnyObject) {
        if (btnPlay.titleLabel?.text == "Play") {
            initPlayer()
            btnPlay.setTitle("Stop", forState: UIControlState.Normal)
        } else {
            stopPlayer()
            btnPlay.setTitle("Play", forState: UIControlState.Normal)
        }
    }

    func initPlayer()  {
        player.play()
    }

    func stopPlayer() {
        // player.currentItem = nil // Last thing I tried, but generate an error
        player.pause()
    }
}

Here are the issues when trying somethings :

player = nil : "Cannot assign a value of type 'NilLiteralCOnvertible' to a value of type 'AVPlayer'"

player.currentItem = nil : "Cannot assign to property: 'currentItem' is a get-only property"


I tried everything, even through AVQueuePlayer without any effective result. (obviously, since I only have one item in my case).

How to stop AVPlayer or destroy his instance ?

Loveliesbleeding answered 7/10, 2015 at 13:44 Comment(7)
player = nil or player.currentItem = nil?Exploit
@JAL, player is an instance of AVPlayer, so I can't just do it. Please see the function stopPlayer(), I have already test thisEcology
What error are you getting when you try to set the player to nil? Also, have you tried removing the player's currentItem like I suggested?Exploit
@JAL, please see my question updatedEcology
You can't mutate a let constant. Change the declaration to var.Exploit
@Exploit I always confuse the two. Thank you for allowing me to fill this important gap!Ecology
@Exploit have you know how to play continues audio after destroyed that ViewController on we have created instance of AVPlayer.Conferva
T
30

If you declare player as an optional variable, you can then set the player to nil to deallocate it.

Silly example but it shows what happens:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    @IBOutlet weak var btnPlay: UIButton!

    var player:AVPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func btnPress(sender: AnyObject) {
        if (btnPlay.titleLabel?.text == "Play") {
            initPlayer()
            btnPlay.setTitle("Stop", forState: UIControlState.Normal)
        } else {
            stopPlayer()
            btnPlay.setTitle("Play", forState: UIControlState.Normal)
        }
    }

    func initPlayer()  {
        if let play = player {
            print("playing")
            play.play()
        } else {
            print("player allocated")
            player = AVPlayer(URL: NSURL(string: "http://streaming.radio.rtl.fr/rtl-1-48-192")!)
            print("playing")
            player!.play()
        }
    }

    func stopPlayer() {
        if let play = player {
            print("stopped")
            play.pause()
            player = nil
            print("player deallocated")
        } else {
            print("player was already deallocated")
        }
    }
}
Tolu answered 7/10, 2015 at 13:58 Comment(2)
Thank you for your answer. I'm sure your solution works, but so how to reallocate the player when re-enter in function initPlayer() ?Ecology
@EricAya have you know how to play continues audio after destroyed that ViewController on we have created instance of AVPlayer.Conferva
S
67

From this post I found the best solution to completely stop AVPlayer before you leave or start a new player:

videoPlayer.replaceCurrentItemWithPlayerItem(nil)

[Update] For SWIFT 3:

player.replaceCurrentItem(with: nil)

Note for 2023. In the case of queue player, it's

qp = AVQueuePlayer()
...
qp.removeAllItems()
Subjunctive answered 26/7, 2016 at 3:18 Comment(2)
Have you know how to play continues audio after destroyed that ViewController on we have created instance of AVPlayer.Conferva
This works! For swift3: videoPlayer.replaceCurrentItem(with: nil)Kapoor
T
30

If you declare player as an optional variable, you can then set the player to nil to deallocate it.

Silly example but it shows what happens:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    @IBOutlet weak var btnPlay: UIButton!

    var player:AVPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func btnPress(sender: AnyObject) {
        if (btnPlay.titleLabel?.text == "Play") {
            initPlayer()
            btnPlay.setTitle("Stop", forState: UIControlState.Normal)
        } else {
            stopPlayer()
            btnPlay.setTitle("Play", forState: UIControlState.Normal)
        }
    }

    func initPlayer()  {
        if let play = player {
            print("playing")
            play.play()
        } else {
            print("player allocated")
            player = AVPlayer(URL: NSURL(string: "http://streaming.radio.rtl.fr/rtl-1-48-192")!)
            print("playing")
            player!.play()
        }
    }

    func stopPlayer() {
        if let play = player {
            print("stopped")
            play.pause()
            player = nil
            print("player deallocated")
        } else {
            print("player was already deallocated")
        }
    }
}
Tolu answered 7/10, 2015 at 13:58 Comment(2)
Thank you for your answer. I'm sure your solution works, but so how to reallocate the player when re-enter in function initPlayer() ?Ecology
@EricAya have you know how to play continues audio after destroyed that ViewController on we have created instance of AVPlayer.Conferva
C
10

SWIFT 3 Version:

player.replaceCurrentItem(with: nil)
Caress answered 22/1, 2018 at 13:53 Comment(1)
player.pause() player.replaceCurrentItem(with: nil)Caress

© 2022 - 2024 — McMap. All rights reserved.