2

In the app, the user is supposed to watch a setup video. If they don't finish watching and click the 'close' button, I want to know where they stopped so I can have the video start at that spot once they start watching again.

I want to know what the time is that they stopped watching so I can save that number to the server for later use, using the following code:

player.seek(to: CMTimeMakeWithSeconds(637, 1))

I tried the following:

func showUnplayedVideo() {

    // 1. check to see if user has already watched the app overview video
    ref.child("videos")
        .child("appOverview")
        .child("watched")
        .observeSingleEvent(of: .value) { (snapshot) in

        let watched = snapshot.value as? Bool ?? false
        if !watched {

            // 2. show setup video popup on first load
            guard let videoURL = URL(string: VideoURL.appOverview.rawValue) else { print("url error"); return }
            let player = AVPlayer(url: videoURL)

            self.playerVC.player = player

            // 3. dismiss the player once the video is over and update Firebase
            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(self.playerDidFinishPlaying),
                                                   name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                                   object: self.playerVC.player?.currentItem)

            NotificationCenter.default.addObserver(self,
                                                   selector: #selector(self.playerWasStoppedPrematurely),
                                                   name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime,
                                                   object: self.playerVC.player?.currentItem)

            self.present(self.playerVC, animated: true) {
                self.playerVC.player?.play()
            }
        }
    }
}

@objc func playerWasStoppedPrematurely(note: NSNotification) {
    self.playerVC.dismiss(animated: true)
    print(playerVC.player?.currentTime())
}

The first notification 'AVPlayerItemDidPlayToEndTime' works great (for users who watch the video all the way through), but my other notification 'AVPlayerItemFailedToPayToEndTime' doesn't work (for users who stop part way through the video).

How do I get the stopping point of my users if they don't watch the whole video?

EDIT #1

This is what the screen looks like when the video is playing:

AVKit

Phontaine Judd
  • 428
  • 7
  • 17

1 Answers1

3

You are presenting the playerVC from a view controller. When the playerVC dismisses, viewDidAppear() in your view controller will be called. This is a choice to put the time checking code.

Original Answer

You are already using player.currentTime(). Why not also put it in the close button handler? Something like this

let current = Double(CMTimeGetSeconds(avPlayer.currentTime()))
ukim
  • 2,395
  • 15
  • 22
  • Excellent suggestion. Just one question: Where is the 'close button handler'? How do I access it? Should I replace my second notification with the 'close button handler'? Pretend I'm a complete noob and don't know what I'm doing :-) Sample code is very helpful. – Phontaine Judd Aug 08 '18 at 05:31
  • @PhontaineJudd You mentioned "user click the 'close' button". How do you handle the close button event? Are you using a IBAction or rewind segue? – ukim Aug 08 '18 at 05:37
  • AVKit automatically creates the 'x' at the top of the screen and the play button and time slider at the bottom. I don't know how to access those properties. – Phontaine Judd Aug 08 '18 at 05:38
  • I added a picture to help clarify. – Phontaine Judd Aug 08 '18 at 05:41
  • @PhontaineJudd I edited my answer, see if that helps – ukim Aug 08 '18 at 05:50
  • Okay, I'm looking into it. I like you answer, but I was really hoping for some 'done button' click event code as part of AVKit or AVPlayer. – Phontaine Judd Aug 08 '18 at 06:02
  • @PhontaineJudd Are you using avplayerviewcontroller? You did not mention that. Set the delegate. Look at the documentation. – ukim Aug 08 '18 at 06:07
  • Yes, I'm using `AVPlayerViewController`. It's declared outside the function: `playerVC = AVPlayerViewController()`. How do I 'set the delegate', and how does that help? I read the documentation, and I am having trouble understanding it. – Phontaine Judd Aug 08 '18 at 06:51
  • @PhontaineJudd Sorry, it seems the delegate is not a good way to do it. Try the `viewDidAppear()` method. Set a flag when you present the playerVC, so when `viewDidAppear()` get called, you will know if it is triggered by the dismiss of playerVC – ukim Aug 08 '18 at 16:15
  • I'm using the viewDidAppear() method, and it's working so far. I'll post my final code when I'm done. Thanks! – Phontaine Judd Aug 08 '18 at 17:17