简体   繁体   中英

iOS Swift cannot dismiss avplayer modal

so here is my use case - we are loading a video using avplayer and playing it, and user can click on the default fullscreen button to take the video fullscreen. The user may be viewing the video in 2 different conditions, if he is logged in and if he is not logged in.

If the user is logged in (determined by a variables value), he can watch full video, otherwise, playback should stop after playing a defined number of seconds (depending on the video the no. of seconds changes), and a banner comes up over the player asking him to login.

Everything is working fine while the video is being played inline. However, when the video is playing fullscreen, then even if we stop playback using didTapPause() , the fullscreen window does not get dismissed. I have even tried dismissing it using self.playerController.dismiss(animated: true, completion: nil) , the fullscreen modal is not dismissed. The code snippet it as follows -

playerController.player?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: DispatchQueue.main) { (CMTime) -> Void in
        if self.playerController.player?.currentItem?.status == .readyToPlay {
            self.videoCurrentTimeDuration = CMTimeGetSeconds((self.playerController.player?.currentItem!.currentTime())!);
            self.videoTimeDuration = CMTimeGetSeconds((self.playerController.player?.currentItem?.duration)!);



            if self.moveToTime != nil{
                let timeWithSecond = CMTimeMakeWithSeconds(self.videoTimeDuration! * self.moveToTime! / 100, Int32(kCMTimeMaxTimescale))

                self.playerController.player?.seek(to: timeWithSecond, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
                self.moveToTime = nil
            }

            guard let videoD = self.videoData else { return }

            let timeTToPlay: Double = Double(videoD.freeDuration)

            if videoD.isFree {
                if videoD.registrationNeeded && !CurrentLoginUser.shared.isLogin{
                    if self.videoCurrentTimeDuration! > timeTToPlay {
                        self.didTapPause()

                        self.playerController.dismiss(animated: true, completion: nil)


                        self.loginNeedView = UINib.get(withNib: self)
                        self.loginNeedView?.frame = self.bounds

                        self.loginNeedView?.autoresizingMask = [
                            UIViewAutoresizing.flexibleWidth,
                            UIViewAutoresizing.flexibleHeight
                        ]
                        self.addSubview(self.loginNeedView!)
                        AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait)
                    }
                }
                else{
                    self.loginNeedView?.removeFromSuperview()
                    AppUtility.lockOrientation(UIInterfaceOrientationMask.all)
                }
            }

The player controller is added onto the view by calling the setupView function which is as follows -

private func setUpView() {
    self.backgroundColor = .black
    addVideoPlayerView()
    configurateControls()
}

fileprivate func addVideoPlayerView() {
    playerController.view.frame = self.bounds
    playerController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    playerController.showsPlaybackControls = true
    playerController.addObserver(self, forKeyPath: "videoBounds", options: NSKeyValueObservingOptions.new, context: nil)
    self.insertSubview(playerController.view, at: 0)
}

I am not sure if this is the proper way to do it, any ideas ?

EDIT:

Next as per anbu.karthik's advice I tried to forcibly remove the fullscreen view by locating the top view controller as :

func currentTopViewController() -> UIViewController {
var topVC: UIViewController? = UIApplication.shared.delegate?.window??.rootViewController
while ((topVC?.presentedViewController) != nil) {
topVC = topVC?.presentedViewController
}
return topVC! 
}

and then, used it as follows-

let currentTopVC: UIViewController? = self.currentTopViewController()

                        if (currentTopVC?.description.contains("AVFullScreenViewController"))! {
                            print("found it")

                            currentTopVC?.dismiss(animated: true) { _ in }
                        }

And it works but crashes the app with the following exception -

Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<AVEmbeddedPlaybackControlsViewController: 0x7fdcc2264400> should have parent view controller:<AVPlayerViewController: 0x7fdcc222a800> but actual parent is:<AVFullScreenViewController: 0x7fdcce2f3c50>'

To my knowledge it is not possible to play full screen directly. It seems that AVPlayerViewController comes pretty much as is and does not offer much in the way of customization of UI or behavior. If you wanted to play full screen directly you would need to either present the controller containing your AVPlayerViewController modally in full screen or change the frame yourself to make it full screen. But there is no API to control full screen programmatically on AVPlayerViewController...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM