AVPlayer sometimes restarts in the middle of playing a video and i'm not sure why. Also, as soon as the view is loaded it begins to play. I want the user to click play first and then let the player start playing.
Here is my code:
 
class VideoPreviewViewController: UIViewController {
// 1
static let assetKeysRequiredToPlay = ["playable","hasProtectedContent"]
// 2
let player = AVPlayer()
// 3
var asset:AVURLAsset? {
    // 9
    didSet {
        guard let newAsset = asset else { return }
        loadURLAsset(newAsset)
    }
}
// 4
var playerLayer:AVPlayerLayer? {
    return playerView.playerLayer
}
// 5
var playerItem:AVPlayerItem? {
    didSet {
        player.replaceCurrentItem(with: self.playerItem)
        player.actionAtItemEnd = .none
    }
}
// 6
var fileLocation:URL? {
    // 10
    didSet {
        self.asset = AVURLAsset(url: self.fileLocation!)
    }
}
@IBOutlet weak var playerView:PlayerView!
@IBOutlet weak var saveButton:UIButton!
@IBOutlet weak var playPauseButton:UIButton!
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    // 11
    addObserver(self, forKeyPath: "player.currentItem.status", options: .new, context: nil)
    addObserver(self, forKeyPath: "player.rate", options: [.new, .initial], context: nil)
    // 14
    NotificationCenter.default.addObserver(self, selector: #selector(playerReachedEnd(notification:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
    // 7
    self.playerView.playerLayer.player = player
}
// 13
override func viewWillDisappear(_ animated: Bool) {
    removeObserver(self, forKeyPath: "player.currentItem.status", context: nil)
    removeObserver(self, forKeyPath: "player.rate", context: nil)
}
override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
// MARK: Main
// 8
func loadURLAsset(_ asset: AVURLAsset) {
    asset.loadValuesAsynchronously(forKeys: VideoPreviewViewController.assetKeysRequiredToPlay) {
        DispatchQueue.main.async {
            guard asset == self.asset else { return }
            for key in VideoPreviewViewController.assetKeysRequiredToPlay {
                var error: NSError?
                if !asset.isPlayable || asset.hasProtectedContent {
                    let message = "Video is not playable."
                    self.showAlert(title: "Error", message: message, dismiss: false)
                    return
                }
                if asset.statusOfValue(forKey: key, error: &error) == .failed {
                    let message = "Failed to load"
                    self.showAlert(title: "Error", message: message, dismiss: false)
                    return
                }
            }
            self.playerItem = AVPlayerItem(asset: asset)
        }
    }
}
// MARK: Actions
@IBAction func closePreview() {
    self.dismiss(animated: true, completion: nil)
}
@IBAction func saveToLibrary() {
    // 18
    self.saveVideoToUserLibrary()
}
@IBAction func playPauseButtonPressed() {
    // 17
    self.updatePlayPauseButtonTitle()
}
// MARK: Callbacks
// 12
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "player.currentItem.status" {
        //Do something
        playPauseButton.isHidden = false
        saveButton.isHidden = false
    }
}
// 15
func playerReachedEnd(notification:NSNotification) {
    //To restart video
    self.asset = AVURLAsset(url: self.fileLocation!)
    self.updatePlayPauseButtonTitle()
}
// MARK: Helpers
func saveVideoToUserLibrary(){
    PhotoManager().saveVideoToUserLibrary(fileUrl: self.fileLocation!) { (success, error) in
        if success {
            self.showAlert(title: "Success", message: "Video saved.", dismiss: true)
        } else {
            self.showAlert(title: "Error", message: (error?.localizedDescription)!, dismiss: false)
        }
    }
}
func showAlert(title:String, message:String, dismiss:Bool) {
    let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)
    if dismiss {
        controller.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            self.dismiss(animated: true, completion: nil)
        }))
    } else {
        controller.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    }
    self.present(controller, animated: true, completion: nil)
}
// 16
func updatePlayPauseButtonTitle() {
    if player.rate > 0 {
        player.pause()
        playPauseButton.setTitle("Play", for: .normal)
    } else {
        player.play()
        playPauseButton.setTitle("Pause", for: .normal)
    }
}
                       
                    
0 Answer(s)