twsmale
twsmale

Reputation: 138

Swift AVPlayerItem close when finished

I'm extremely new to Swift and iOS development, so please forgive my ignorance.

I'm trying to have the AVPlayer close automatically when the video is done playing. I've thought to attach the "playerDidFinishPlaying" listener to receive the notification, but once I have it, I can't find the method/event to close the Controller. I'm looking to mimic the action of clicking the "Done" button.

Here is a small snippet of code. Hopefully this is enough information. If not, I can provide further info

let destination = segue.destinationViewController as! AVPlayerViewController
let url = NSURL(string: "video url")
destination.player = AVPlayer(URL: url!)
destination.player?.play()

I've added the following notification, but again, I'm not sure what to do with it once I have it...

NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", 
    name: AVPlayerItemDidPlayToEndTimeNotification, 
    object: destination.player!.currentItem)

func playerDidFinishPlaying(note:NSNotification){
    print("finished")
    // close window/controller
}

Lastly, I know I'll need to remove the observer, but I'm not sure when or where to do so. Any help is greatly appreciated.

Upvotes: 2

Views: 5921

Answers (3)

Ketan Sodvadiya
Ketan Sodvadiya

Reputation: 514

for #iOS 11 and swift 4.2 dismiss controller are not work so just add this key in your player setup code

if #available(iOS 11.0, *) {
     self.playerVC?.exitsFullScreenWhenPlaybackEnds = true
}

if you wan to allow #iOS 10 as well then write this line.

if #available(iOS 11.0, *) {
      self.playerVC?.exitsFullScreenWhenPlaybackEnds = true
 }

NotificationCenter.default.addObserver(self, selector: #selector(self.playerItemDidReachEnd(notification:)), name: .AVPlayerItemDidPlayToEndTime, object:self.playerVC?.player!.currentItem)

func playerItemDidReachEnd(note:NSNotification){
     print("finished")
     dismissViewControllerAnimated(true, completion: nil)
 }

Upvotes: 2

MLBDG
MLBDG

Reputation: 1367

Update for SWIFT 3:

Notes: The viewController where you are playing the audio needs: AVAudioPlayerDelegate

Also you dont need an observer

class myViewController: UIViewController, AVAudioPlayerDelegate {

var audioplayer = AVAudioPlayer() 

override func viewDidAppear(_ animated: Bool) {

if soundsON{
        let myFilePathString = Bundle.main.path(forResource: "backgroundSound", ofType: "mp3")

        if let myFilePathString = myFilePathString
        {
            let myFilePathURL = URL(fileURLWithPath: myFilePathString)

            do{
                try audioplayer = AVAudioPlayer(contentsOf: myFilePathURL)
                audioplayer.delegate = self
                audioplayer.prepareToPlay()

                audioplayer.play()


            }catch{
                print("error playing coin sound")
            }
        }
   }    
}

In this example the sound will play at viewDidAppear, and when it finishes it will call: audioPlayerDidFinishPlaying:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    //Check if the sound that finishes comes from a certain AVAudioPlayer 
    if player == audioplayer{
        print("The sound from -audioplayer- has finished")
    // If you need to dismiss the VC:
        dismiss(animated: true, completion: nil)
    }
}

Upvotes: 0

Breek
Breek

Reputation: 1441

In order to "close" the controller, you should call dismissViewControllerAnimated(true, completion: nil)

So the code will look like:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", 
    name: AVPlayerItemDidPlayToEndTimeNotification, 
    object: destination.player!.currentItem)

func playerDidFinishPlaying(note:NSNotification){
    print("finished")
    dismissViewControllerAnimated(true, completion: nil)
}

if your viewController is inside of a UINavigationController stack, you can also do:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", 
        name: AVPlayerItemDidPlayToEndTimeNotification, 
        object: destination.player!.currentItem)

func playerDidFinishPlaying(note:NSNotification){
    print("finished")
    navigationController?.popViewControllerAnimated(true)
}

And for remove the observer, you can do within deinit{}:

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

Upvotes: 4

Related Questions