AVPictureInPictureController cannot activate programmatically during a scrolling

1.4k views Asked by At

I have a video in a cell, if I put it in PIP mode with the button everything works fine but if I do it programmatically when the cell go out of screen doesn't not automatically put in PIP mode, can just activate it via a button?

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard let cell = self.playerCell, self.playerController != nil else {
        return
    }
    
    let rect = self.view.convert(cell.frame, from: scrollView)
    if rect.origin.y < 0, self.pipController == nil {
        self.pipController = self.startPictureInPicture()
    }
}

func startPictureInPicture() -> AVPictureInPictureController? {
    guard AVPictureInPictureController.isPictureInPictureSupported() else {
        return nil
    }
    
    let layer = AVPlayerLayer(player: self.playerController.player)
    try? AVAudioSession.sharedInstance().setActive(true)
    if let pipController = AVPictureInPictureController(playerLayer: layer) {
        if pipController.isPictureInPicturePossible {
            pipController.startPictureInPicture()
        } else {
            pipController.addObserver(self, forKeyPath: "isPictureInPicturePossible", options: [.new, .initial], context: nil)
        }
    }
    
    return nil
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "isPictureInPicturePossible", let pipController = object as? AVPictureInPictureController, pipController.isPictureInPicturePossible {
        pipController.startPictureInPicture()
    }
}

UPDATE: the debug console always show a warning Unbalanced calls to begin/end appearance transitions for <UIViewController>. but this I have solved with:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    pipController.startPictureInPicture()
}
1

There are 1 answers

0
atulkhatri On

As per Apple's guidelines, we should not start PIP mode without user's action.

Only begin Picture in Picture playback in response to user interaction and never programmatically. The App Store review team rejects apps that fail to follow this requirement.

Source: https://developer.apple.com/documentation/avkit/adopting_picture_in_picture_in_a_custom_player

I would suggest you create your own custom PIP view inside the app to avoid rejection.