1

My app plays video throughout several vcs using AVFoundation. For example FirstController plays a video then a user can push on SecondController which also plays a video then they can push on the ThirdController which also plays a video... The same thing would apply if their switching tabs. There's a video screen on TabOne, TabTwo, and TabThree.

Instead of setting up all the playLayer code associated with AVFoundation in each class I created one class that contains a AVPlayerViewController() and add that class to each vc using addChildViewController().

The problem is since I have one class that manages AVFoundation the Notification.Name.AVPlayerItemDidPlayToEndTime that gets notified when the player finishes playing can't distinguish one video on one vc from another video in a different vc. For example after a video finishes playing I show a replayButton. If the video in the first tab is playing, when I switch to TabTwo I pause that video, after the video on TabTwo finishes and the replayButton appears, if I switch back to TabOne, the replayButton will also appear on TabOne's screen (it should still show the pause button).

The problem is even though I have different instances of the AVFoundationManager, all the instances access the one showReplayButton() function that gets triggered when the notification fires.

How can I get around this?

I know I can check on the parent of the AVFoundationManager to find out which parent is managing it and use that inside the showReplayButton() function but I don't know which check to run on it.

AVFoundationManager:

class AVFoundationManager: UIViewController {

    ....

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

    func configureAVPlayerController() {

        let avPlayerVC = AVPlayerViewController()
        avPlayerVC.player = player
        avPlayerVC.view.frame = view.bounds
        avPlayerVC.showsPlaybackControls = false
        avPlayerVC.videoGravity = AVLayerVideoGravity.resizeAspectFill.rawValue
        addChildViewController(avPlayerVC)
        view.addSubview(avPlayerVC.view)
        avPlayerVC.didMove(toParentViewController: self)

        player?.replaceCurrentItem(with: playerItem!)
        player?.play()

        NotificationCenter.default.addObserver(self, selector: #selector(showReplayButton), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)

        playerItem?.addObserver(self, forKeyPath: #keyPath(AVPlayerItem.status),
                            options: [.old, .new],
                            context: &itemContext)
    }

    @obj func showReplayButton(){

        // if self.parent ... run a bool on the parent and enclose these two in the paranthesis?
        pausePlayButton.isHidden = true
        replayButton.isHidden = false
    }
}

TabOneClass:

let avFoundationManager = AVFoundationManager()
addChildViewController(avFoundationManager)
avFoundationManager.didMove(toParentViewController: self)

TabTwoClass:

let avFoundationManager = AVFoundationManager()
addChildViewController(avFoundationManager)
avFoundationManager.didMove(toParentViewController: self)

FirstController (root) in TabThree:

let avFoundationManager = AVFoundationManager()
addChildViewController(avFoundationManager)
avFoundationManager.didMove(toParentViewController: self)

SecondController (child) in TabThree:

let avFoundationManager = AVFoundationManager()
addChildViewController(avFoundationManager)
avFoundationManager.didMove(toParentViewController: self)
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
  • I had a similar problem, not quite that many videos though. I basically removed the previous notification observer on the setup, then re-added the new one, when setting up the new video – Paulo Jun 24 '18 at 17:35
  • so you added the notification outside the class? Instead of me adding it inside the AVFoundationManager(), I remove it from there and add it individually to FirstController, SecondController, etc. Then when viewWillDisappear runs I remove it? – Lance Samaria Jun 24 '18 at 17:37
  • I'll try it when I get back home later tonight, thanks – Lance Samaria Jun 24 '18 at 17:39
  • Yeah, I created a function in the manager class, and fired that when I needed to – Paulo Jun 24 '18 at 17:40
  • I know to how to do it but you should add it as an answer so if it works i'll accept it – Lance Samaria Jun 24 '18 at 17:41

2 Answers2

0

I’m not saying this is the best answer, and if anyone else can come up with a better solution, please post :) From my understanding, the player cannot distinguish between the number of observers.

(Side note, currently on my phone, so apologies for the pseudo code)

class PlayerViewController {
// other code and functions
    func removeObservers() {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

In the viewWillDisappear call the remove observers function

Just remember to re-initialize your observers when you need them, either when you get the view to appear, or when you initialize the next video.

Paulo
  • 602
  • 1
  • 8
  • 20
  • nah it didn’t work. The problem is the function that shows the replay button is inside the ABFoundationManager. Any class that sends it a notification it will notify the play to show the reply button. Thanks for the help anyway – Lance Samaria Jun 25 '18 at 01:07
0

I got the answer from here

Inside the Notification, instead of setting the last argument object to nil set it to player.currentItem:

like this:

NotificationCenter.default.addObserver(self, selector: #selector(showReplayButton),
                                     name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
                                     object: player?.currentItem)
Lance Samaria
  • 17,576
  • 18
  • 108
  • 256