skip to Main Content

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

3

Answers


  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];
    
    Login or Signup to reply.
  2. 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>) {
     }
    

    }

    Login or Signup to reply.
  3. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search