I have a simple application in which the portrait of the UINavigationController represents the landscape of the UINavigationController . It usually works fine. Sometimes, however, the landscape view manager is displayed in portrait orientation, but with landscape boundaries.
Here's how it works: to limit the orientation of the navigation controllers, I have an OrientableNavigationController class that comes from the UINavigationController and exposes rotation-specific properties:
class OrientableNavigationController: UINavigationController { private var _supportedInterfaceOrientations: UIInterfaceOrientationMask = .all private var _shouldAutorotate: Bool = false private var _preferredInterfaceOrientationForPresentation: UIInterfaceOrientation = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { get { return _supportedInterfaceOrientations } set { _supportedInterfaceOrientations = newValue } } override var shouldAutorotate: Bool { get { return _shouldAutorotate } set { _shouldAutorotate = newValue } } override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { get { return _preferredInterfaceOrientationForPresentation } set { _preferredInterfaceOrientationForPresentation = newValue } } }
I run one of them in AppDelegate, give it a view controller and set it as the rootViewController window:
private var portraitNavigationController = OrientableNavigationController() func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { portraitNavigationController.supportedInterfaceOrientations = .portrait portraitNavigationController.shouldAutorotate = true portraitNavigationController.preferredInterfaceOrientationForPresentation = .portrait let portraitViewController = PortraitViewController() portraitViewController.delegate = self portraitNavigationController.pushViewController(portraitViewController, animated: false) window = UIWindow(frame: UIScreen.main.bounds) window!.rootViewController = portraitNavigationController window!.makeKeyAndVisible() return true }
It looks like this:

And that the "Present Landscape View Controller" button is connected for this:
func portraitViewControllerButtonWasTouched(_ viewController: PortraitViewController) { let landscapeNavigationController = OrientableNavigationController() landscapeNavigationController.supportedInterfaceOrientations = .landscape landscapeNavigationController.shouldAutorotate = true landscapeNavigationController.preferredInterfaceOrientationForPresentation = .landscapeLeft landscapeNavigationController.isNavigationBarHidden = true let landscapeViewController = LandscapeViewController() landscapeNavigationController.pushViewController(landscapeViewController, animated: false) portraitNavigationController.present(landscapeNavigationController, animated: true) }
In most cases, this works great. The landscape view controller is presented as follows:

But sometimes this happens:

This happens both in the simulator and in the device. Any ideas?
source share