7

In previous versions of iOS, loading AVPlayerViewController (as well as SwiftUI VideoPlayer) with a video would display the first frame and include a play icon in the center but this has gone away in iOS 16. I've been relying on that UI element as an affordance for "There's a video here, tap it".

Plus, now tapping the video shows the playback controls over the video for a few seconds instead of just starting playback.

Does anyone know if:

  • There's a property or configuration option to show the play icon?
  • I should be providing my own play icon overlay placed over the video manually?
  • This is a bug in iOS 16?

iOS 15.5 simulator with play icon, iOS 16 missing play icon

toemat
  • 150
  • 1
  • 9
  • Im having the same problem in iOS 16, works fine in iOS 15. For me if I have the VideoPlayer in a TabView, if I hide the TabView controls it seems to also hide the VideoPlayer controls. I believe its an iOS 16 issue. – 1337holiday Sep 16 '22 at 20:29
  • Working with `AVPlayer` on simulator is tricky, does it behave the same on real device? – Mr.SwiftOak Sep 19 '22 at 12:11
  • 3
    Same on our live app for iOS 16 devices. Play button is not displayed. – Benoit Deldicque Sep 19 '22 at 14:14

3 Answers3

0

For Swift UI need to use

CustomVideoPlayer()
    .compositingGroup() // Mandatory 


struct CustomVideoPlayer : UIViewControllerRepresentable {

 var player: AVPlayer

 func makeUIViewController(context: UIViewControllerRepresentableContext<CustomVideoPlayer>) -> AVPlayerViewController {
     
     let controller = AVPlayerViewController()
     controller.player = player
     return controller

 }

 func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext<CustomVideoPlayer>) {
 }

}

  • This seems to be unrelated to the problem of the system provided play icon overlay. – toemat Nov 02 '22 at 16:01
  • If you have a new question, please ask it by clicking the [Ask Question](https://stackoverflow.com/questions/ask) button. Include a link to this question if it helps provide context. - [From Review](/review/late-answers/33089336) – coturiv Nov 07 '22 at 09:55
0

I think a work around for this issue can be adding

if #available(iOS 16.0, *) {
    avPlayerViewController.setValue(false, forKey: "canHidePlaybackControls")
}

and changing it back after one second. So the code will look like something like this:

let avPlayer: AVPlayer = AVPlayer(url: newURL)
avPlayerViewController = AVPlayerViewController()
if let avPlayerViewController = avPlayerViewController {
    avPlayerViewController.delegate = self
    avPlayerViewController.player = avPlayer
    if #available(iOS 16.0, *) {
        avPlayerViewController.setValue(false, forKey: "canHidePlaybackControls")
    }
    addChild(avPlayerViewController)
    view.addSubview(avPlayerViewController.view)
}
if #available(iOS 16.0, *) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
        self.avPlayerViewController?.setValue(true, forKey: "canHidePlaybackControls")
    })
}

The downside of using this work around is that you'll be using private api calls which can result in your app being rejected by Apple.

Negar Bean
  • 65
  • 9
-1

Make sure to add the AVPlayerViewController as a child view controller of your own view controller like this as mentioned here:

Swift:

addChild(playerController)

Objective-C:

[self addChildViewController:playerController];
Frederik
  • 467
  • 6
  • 16
  • The demo app used for the screenshots adds the child view controller in this way, so it seems to not seem to fix the situation. – toemat Nov 01 '22 at 19:14