1
votes

Okay So I have one view controller that is an AVPlayer. I want that controller to be able to rotate to landscape mode and portrait freely

import Foundation
import UIKit
import AVFoundation
import AVKit

class EventPromoVideoPlayer: UIViewController {
    public var eventKey = ""

    override var prefersStatusBarHidden: Bool {
        return true
    }
    //URL of promo video that is about to be played
    private var videoURL: URL
    // Allows you to play the actual mp4 or video
    var player: AVPlayer?
    // Allows you to display the video content of a AVPlayer
    var playerController : AVPlayerViewController?

    init(videoURL: URL) {
        self.videoURL = videoURL
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.gray
        let downSwipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeAction(_:)))
        downSwipe.direction = .down
        view.addGestureRecognizer(downSwipe)


        //Setting the video url of the AVPlayer
        player = AVPlayer(url: videoURL)
        playerController = AVPlayerViewController()

        guard player != nil && playerController != nil else {
            return
        }
        playerController!.showsPlaybackControls = false
        // Setting AVPlayer to the player property of AVPlayerViewController
        playerController!.player = player!
        self.addChildViewController(playerController!)
        self.view.addSubview(playerController!.view)
        playerController!.view.frame = view.frame
        // Added an observer for when the video stops playing so it can be on a continuous loop
        NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: self.player!.currentItem)
        //TODO: Need to fix frame of x and y
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        player?.play()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.navigationBar.isHidden = true
        tabBarController?.tabBar.isHidden = true
    }

    override var supportedInterfaceOrientations:UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.all
    }
    // Allows the video to keep playing on a loop
    @objc fileprivate func playerItemDidReachEnd(_ notification: Notification) {
        if self.player != nil {
            self.player!.seek(to: kCMTimeZero)
            self.player!.play()
        }
    }

    @objc func cancel() {
        dismiss(animated: true, completion: nil)
    }

    @objc func swipeAction(_ swipe: UIGestureRecognizer){
        if let swipeGesture = swipe as? UISwipeGestureRecognizer {
            switch swipeGesture.direction {
            case UISwipeGestureRecognizerDirection.right:
                print("Swiped right")
                break
            case UISwipeGestureRecognizerDirection.down:
                print("Swiped Down")
                dismiss(animated: true, completion: nil)
                break
            case UISwipeGestureRecognizerDirection.left:
                print("Swiped left")
                break
            case UISwipeGestureRecognizerDirection.up:
                print("Swiped up")
                break
            default:
                break
            }
        }
    }
}

When I dismiss the screen I still need the previous controller to be in portrait. This shouldnt be a problem seeing as portrait mode is locked in as the only orientation in my settings and I want to keep it that way. However I want this one screen to be able to move freely. Any ideas and hints would be greatly appreciated.

The app delegate method does not work for me. Neither does overriding shouldAutoRotate or supportedInterfaceOrientations in the function

1

1 Answers

0
votes

You can use the below method in app delegate.

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    if let rootViewController = UIApplication.topViewController() {
        if (rootViewController.responds(to: Selector(("canRotate")))) || String(describing: type(of: rootViewController)) == "AVFullScreenViewController" {
            // Unlock landscape view orientations for this view controller
            return .allButUpsideDown;
        }
    }
    // Only allow portrait (standard behaviour)
    return .portrait
}

Add the below method in view controller where you want to display as landscape.

func canRotate() -> Void {}

extension UIApplication {

  class func topViewController(base: UIViewController? = (UIApplication.sharedApplication().delegate as! AppDelegate).window?.rootViewController) -> UIViewController? {
    if let nav = base as? UINavigationController {
       return topViewController(base: nav.visibleViewController)
    }
    if let tab = base as? UITabBarController {
      if let selected = tab.selectedViewController {
         return topViewController(base: selected)
      }
    }
    if let presented = base?.presentedViewController {
        return topViewController(base: presented)
    }
    return base
}