I have the following view controller set up:
viewController1 is able rotate freely to any orientation except portrait upside down.
viewController2 gets pushed on top of viewController1, and I'd like for it to be the same orientation viewController1 is and I'd like for it not to be able to rotate.
viewController3 gets pushed on top of viewController2. I'd like for viewController3 to be in portrait mode.
I'm having a lot of issues trying to accomplish this in iOS6 (haven't tried yet in iOS5). First off, I have already created my own Navigation Controller and put the following in it:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (BOOL) shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
I've tried a lot of different combinations of these things to know avail. Mainly where I'm struggling is forcing vc3 to be presented as portrait if vc2 is in landscape. Any help would be appreciated.
I have explained in a different answer that it is not supported, in iOS 6, to force rotation when pushing a new view controller on to a navigation controller. You can structure rules about compensatory rotation (i.e. what should happen if the user rotates the device), but you can't force the interface to rotate. The only situation in which iOS 6 is happy to let you force rotation is when presenting or dismissing a view controller (
presentViewController:animated:
anddismissViewControllerAnimated:
).However, it is possible to use a presented view controller in such a way that it kind of looks like you're pushing onto the navigation controller. I've made a movie showing what I mean:
http://youtu.be/O76d6FhPXlE
Now, that's not totally perfect by any means. There is no rotation animation of the status bar, and there is a kind of black "blink" between the two views - which is intentional, because it's there to cover up what is really going. What's really going on is that there are really two difference navigation controllers and three view controllers, as shown in this screen shot of the storyboard.
What we have is:
a nav controller subclass set to portrait orientation, and its root view controller
a second nav controller subclass set to landscape orientation, and its root view controller, which is black and functions as an intermediary
a third view controller to be pushed onto the second nav controller's stack
When the user asks to go "forward" from the first view controller, we present the second navigation controller, thus seeing the black view controller momentarily, but then we immediately push the third view controller. So we get forced rotation, along with a kind of black flash and a push animation. When the user taps the Back button in the third view controller, we reverse the process.
All the transitional code is in the black view controller (ViewControllerIntermediary). I've tried to tweak it to give the most satisfying animation I can:
And for Swift
For more details check this link
What you're trying to do here is fighting the framework. What you're describing is simply not how a navigation controller architecture works in iOS 6. If you want to show a view controller's view and force rotation, use a presented view controller. That's the only time
preferredInterfaceOrientationForPresentation
is meaningful, and your view controller'ssupportedInterfaceOrientations
will actually be consulted because, being presented, it will be at the root of the interface.