10

I am making a simple iPad app to play a movie when a button is pressed. The movie plays and when the movie is finished I want to close AVPlayerView so it goes back to the main screen. Currently when the video finishes it stays on the last frame. My ViewController.Swift at the moment.

import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {
//MARK : Properties 

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}
//MARK: Actions

@IBAction func playButton(_ sender: AnyObject) {

    let movieURL = Bundle.main.url(forResource: "ElephantSeals", withExtension: "mov")!
    let player = AVPlayer(url: movieURL as URL)

    let playerViewController = AVPlayerViewController()

    playerViewController.player = player

    self.present(playerViewController, animated: true) {
        playerViewController.player!.play()
        }
//    player.actionAtItemEnd = playerViewController.dismiss(animated: true)
}
}

As you can see, I think there might be something in actionAtItemEnd, but I'm not sure how to implement it. Thank you.

RoryM
  • 125
  • 1
  • 1
  • 6

6 Answers6

23

This is working code in swift 5.3 and iOS 14.2, try this and let me know...:)

import UIKit
import AVKit
import AVFoundation

class ViewController: UIViewController {
    
    let playerViewController = AVPlayerViewController()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    @IBAction func playButton(_ sender: AnyObject) {
        
        let movieURL = Bundle.main.url(forResource: "ElephantSeals", withExtension: "mp4")!
        let player = AVPlayer(url: movieURL as URL)
        
        playerViewController.player = player
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerViewController.player?.currentItem)
        
        self.present(playerViewController, animated: true) {
            self.playerViewController.player!.play()
        }
    }
    
    
    @objc func playerDidFinishPlaying(note: NSNotification) {
        self.playerViewController.dismiss(animated: true)
    }
}

You can download sample project for same from here https://github.com/deepakiosdev/AVPlayerViewControllerDemo

Dipak
  • 2,263
  • 1
  • 21
  • 27
  • 1
    Thank you very much, very clear to understand. This worked for me! – RoryM Oct 20 '16 at 01:11
  • When the player finishes playing, the current time is not set to zero, if the user tries to play the video again it will start at the end. In the playerDidFinishPlaying call seek(to: CMTime(seconds: 0.0, preferredTimescale: 1) on the player.currentItem. Also, the .AVPlayerItemDidPlayToEndTime Notification carries a warning "This notification may be posted on a different thread than the one on which the observer was registered." So dismissing the AVPlayerViewController should be done on the main thread. – Leon Feb 18 '18 at 17:15
6

Swift 4

let playerController = AVPlayerViewController()

private func playVideo() {
    guard let path = Bundle.main.path(forResource: "p810", ofType:"mp4") else {
        debugPrint("video.m4v not found")
        return
    }
    let player = AVPlayer(url: URL(fileURLWithPath: path))
    playerController.player = player
    NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerController.player?.currentItem)

    present(playerController, animated: true) {
        player.play()
    }
}

@objc func playerDidFinishPlaying(note: NSNotification) {
    playerController.dismiss(animated: true, completion: nil)
}
Ahmed Safadi
  • 4,402
  • 37
  • 33
2

Using NSNotificationCenter you can do this .

 NotificationCenter.default.addObserver(self, selector: #selector(ViewController.playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object:  videoPlayer!.currentItem)

@objc func playerDidFinishPlaying(note: NSNotification) {
    // here you can do your dismiss controller logic
    AVPlayerViewController.dismiss(animated: true)
    print("Video Finished")
}
krishnan muthiah pillai
  • 2,711
  • 2
  • 29
  • 35
KKRocks
  • 8,222
  • 1
  • 18
  • 84
  • Xcode told me two things on the first line of this code: 'NSNotificationCenter' has been renamed to 'NotificationCenter' – RoryM Oct 18 '16 at 23:25
1

here is objective c code

[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(nextVideo:)  name:AVPlayerItemDidPlayToEndTimeNotification object:playerViewController.player.currentItem];
0

Invoke AVPlayerViewControllerDelegate.

In viewDidLoad initialize the delegate and implement this method

func playerViewControllerDidStopPictureInPicture(AVPlayerViewController) {
      AVPlayerViewController.dismiss(animated: true)
}

https://developer.apple.com/reference/avkit/avplayerviewcontrollerdelegate

Sofeda
  • 1,361
  • 1
  • 13
  • 23
0

You don't need to setup notification observer. Just use exitsFullScreenWhenPlaybackEnds property of the player controller:

let playerViewController = AVPlayerViewController()
playerViewController.exitsFullScreenWhenPlaybackEnds = true
playerViewController.player = AVPlayer(url: url)
navigationController.present(playerViewController, animated: true, completion: nil)
playerViewController.player?.play()

https://developer.apple.com/documentation/avkit/avplayerviewcontroller/2875793-exitsfullscreenwhenplaybackends

Hopreeeenjust
  • 257
  • 4
  • 5