Reputation: 2850
I have two classes which subclass from UIViewController
. PortraitViewController
and LandscapeViewController
.
These classes have their vars shouldAutorotate
, supportedInterfaceOrientations
and preferredInterfaceOrientationForPresentation
with override implementation so they can stick to portrait or landscape orientation accordingly.
My application accepts Portrait and Landscape mode.
Now, I also have:
ViewController1
which subclasses from PortraitViewController
ViewController2
which subclasses from LandscapeViewController
When I show ViewController1
with a UINavigationController
attached to it, it sticks with portrait as expected.
When I show ViewController2
with a UINavigationController
attached to it, as a modal nav on top of ViewController1
, it sticks with landscape as expected.
There's an extension for UINavigationController
which also overrides the vars mentioned above, but it reads properties from the visibleController
parameter.
But when I dismiss ViewController2
, ViewController1
appears in landscape.
How can I make ViewController1
stick in portrait mode, regardless of what I show on top of it?
Note: Every time the device is in portrait mode.
EDIT:
Here's a demo project: https://www.dropbox.com/s/ishe88e1x81nzlp/DemoOrientationApp.zip?dl=0
Upvotes: 0
Views: 68
Reputation: 534893
Okay, so:
Throw away your UINavigationControllerExtension.
Change your Info.plist so that we launch only into portrait:
(Delete items 1 and 2.)
In the app delegate, add this code, to allow us to rotate to landscape after launch:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return .all
}
In ViewController, fix the code as follows:
class ViewController: PortraitViewController, UINavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return self.supportedInterfaceOrientations
}
@IBAction func showView(_ sender: Any) {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController2") as! ViewController2
let nav = UINavigationController(rootViewController: vc)
nav.delegate = vc
present(nav, animated: true, completion: nil)
}
}
In ViewController2, fix the code as follows:
class ViewController2: LandscapeViewController, UINavigationControllerDelegate {
func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return self.supportedInterfaceOrientations
}
func navigationControllerPreferredInterfaceOrientationForPresentation(_ navigationController: UINavigationController) -> UIInterfaceOrientation {
return self.preferredInterfaceOrientationForPresentation
}
@IBAction func dismiss(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
The app now behaves as desired.
Upvotes: 0
Reputation: 904
The visibleViewController is either the top view controller of the navigation stack or a view controller presented from the navigation controller.
So, when you present the second navigation controller, the first navigation controller reads the second navigation controller property which passes back the landscape view controller's property.
What you need to use instead is topViewController. That way, the setting is limited to the view controller stack.
Upvotes: 1