I have an iPhone app that uses a UINavigationController
to present a drill-down interface: First one view, then another, up to four levels deep. I want the first three views restricted to portrait orientation and only the last view should be allowed to rotate to landscape. When returning from the fourth view to the third and the fourth view was in landscape orientation I want everything to rotate back to portrait.
In iOS 5 I simply defined shouldAutorotateToInterfaceOrientation:
in each of my view controllers to return YES for the allowable orientations. Everything worked as described above, including the return to portrait even if the device was being held in landscape orientation when returning from view controller #4 to #3.
In iOS 6 all view controllers rotate to landscape, breaking those that weren't meant to. The iOS 6 release notes say
More responsibility is moving to the app and the app delegate. Now, iOS containers (such as
UINavigationController
) do not consult their children to determine whether they should autorotate. [...] The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style. Moreover, the supported orientations are retrieved only if this view controller returns YES from itsshouldAutorotate
method. [...] The system determines whether an orientation is supported by intersecting the value returned by the app’ssupportedInterfaceOrientationsForWindow:
method with the value returned by thesupportedInterfaceOrientations
method of the top-most full-screen controller.
So I subclassed UINavigationController
, gave my MainNavigationController
a boolean property landscapeOK
and used this to return the allowable orientations in supportedInterfaceOrientations
. Then in each of my view controllers' viewWillAppear:
methods I have a line like this
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
to tell my MainNavigationController
the desired behavior.
Here comes the question: If I now navigate to my fourth view in portrait mode and turn the phone over it rotates to landscape. Now I press the back button to return to my third view which is supposed to work portrait only. But it doesn't rotate back. How do I make it do that?
I tried
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]
in the viewWillAppear
method of my third view controller, but it doesn't do anything. Is this the wrong method to call or maybe the wrong place to call it or should I be implementing the whole thing in a totally different way?
You want to Force iOS 6 app portrait only then you can add to a UIViewController subclass below methods
I wanted to have all my VCs locked to portrait orientation except one. This is what worked for me.
In the root view controller, detect the kind of view controller thats on top of the window and set the orientation of the app accordingly in the supportedInterfaceOrientations method. For example, I needed my app to rotate only when the webview was on top of the stack. Here's what I added in my rootVC :
Add a CustomNavigationController
Override these methods in it:
Now add all orientations in the plist
In the view controller add only the required ones:
these methods override the navigation controller methods
Please use the following method to solve this issue
return only the orientation you want!!!
After looking through every answer in countless similar questions on SO, none of the answers worked for me, but they did give me some ideas. Here's how I ended up solving the problem:
First, make sure your Supported Interface Orientations in your project's target contain all orientations that you want for your rotating view.
Next, make a category of
UINavigationController
(since Apple says not to subclass it):Import that category and the view controller that you want to be able to rotate (which I'll call
RotatingViewController
) to your highest level view controller, which should contain your navigation controller. In that view controller, implementshouldAutorotate
as follows. Note that this should not be the same view controller that you want to rotate.Finally, in your
RotatingViewController
, implementshouldAutorotate
andsupportedInterfaceOrientations
as follows:The reason you need to do this is because iOS 6 gives control of rotation to the root view controller instead of the top view controlller. If you want an individual view's rotation to behave differently than other views in the stack, you need to write a specific case for it in the root view controller.
I'd like to give a partial answer to my own question. I found the following line of code, used in the
viewWillAppear
method of my thirdUIViewController
, to work:But I don't really like this solution. It is using a trick to assign to a read-only property which according to Apple documentation represents the physical orientation of the device. It's like telling the iPhone to jump to the correct orientation in the hand of the user.
I am very tempted to leave this in my app since it simply works. But it doesn't feel right so I'd like to leave the question open for a clean solution.