AVPlayerViewController stops after returning from full screen

3.8k views Asked by At

I have an AVPlayerViewController which I initialize with an AVPlayer and some AVPlayerItem (iOS 10, Xcode 8, Objective C). The AVPlayerViewController is presented "inline" inside some subview, and everything works perfectly with the native playback controls.

When I press the native fullscreen button, it also works ok and switches to full screen mode (with Done button on top left).

My problem is when I press the Done button to return from full screen, the player for some reason stops playing, resets itself, and if I check .currentItem, I see it's nil.

What's happening here? Why can't AVPlayerViewController maintain its AVPlayerItem in between switching from/to full screen?

4

There are 4 answers

4
bauerMusic On BEST ANSWER

Since it looks like the current behavior of AVPlayerViewController is to pause when exiting full screen, we can call play() when exiting by implementing the delegate:

class VideoView {

    private var playerViewController: AVPlayerViewController?

    func something() {

        playerViewController = AVPlayerViewController()

        // Other setups

        playerViewController?.delegate = self
    }
}

extension VideoView: AVPlayerViewControllerDelegate {

    func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {

        // The system pauses when returning from full screen, we need to 'resume' manually.
        coordinator.animate(alongsideTransition: nil) { transitionContext in
            self.playerViewController?.player.play()
        }
    }
}
2
mllm On

Using @matt's reference, I saw that what I'd done different was to set the AVPlayerViewController's player property without an AVPlayerItem, and only setting it afterwards (relying on replaceCurrentItemWithPlayerItem().

In other words - from my experience, you should initialize both the AVPlayerViewController AND the AVPlayer with URL or any AVPlayerItem and only then adding the AVPlayerViewController as a child view controller.

Code for using without AutoLayout:

if let playerView = self.playerView {
    let playerItem = AVPlayerItem(url: self.url)
    let player = AVPlayer(playerItem: playerItem)

    let playerVc = AVPlayerViewController()
    playerVc.player = player

    self.addChildViewController(playerVc)
    playerVc.view.frame = playerView.bounds
    playerView.addSubview(playerVc.view)
    playerVc.didMove(toParentViewController: self)

    player.play()
}
0
daihovey On

Following on from the above answer https://stackoverflow.com/a/58818395/196555 and the comment AVPlayerViewController stops after returning from full screen

I found using this extension works if you want to know if the AVPlayerViewController is playing or not

extension AVPlayer {
    var isPlaying: Bool {
        rate != 0 && error == nil
    }
}

 @objc func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        let isPlaying = self.playerViewController.player?.isPlaying ?? false
        // The system pauses when returning from full screen, we need to 'resume' manually.
        coordinator.animate(alongsideTransition: nil) { _ in
            if isPlaying {
                self.playerViewController.player?.play()
            }
        }
    }
0
闪电狮 On

The above solution will always play the video on exit full screen, even if it is paused.

Add this to fix it :

func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    let 获取播放状态 = self.parent.player.isPlaying
    
       // The system pauses when returning from full screen, we need to 'resume' manually.
       coordinator.animate(alongsideTransition: nil) { transitionContext in
           if 获取播放状态 {
               self.parent.player.play()
           }
       }
   }

And

extension AVPlayer {
    var isPlaying: Bool {
        return rate != 0 && error == nil
    }
}