How to force a UIViewController to Portrait orientation in iOS 6
If you want all of our navigation controllers to respect the top view controller you can use a category so you don't have to go through and change a bunch of class names.
@implementation UINavigationController (Rotation_IOS6)-(BOOL)shouldAutorotate{ return [[self.viewControllers lastObject] shouldAutorotate];}-(NSUInteger)supportedInterfaceOrientations{ return [[self.viewControllers lastObject] supportedInterfaceOrientations];}- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{ return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];}@end
As a few of the comments point to, this is a quick fix to the problem. A better solution is subclass UINavigationController and put these methods there. A subclass also helps for supporting 6 and 7.
The best way for iOS6 specifically is noted in "iOS6 By Tutorials" by the Ray Wenderlich team - http://www.raywenderlich.com/ and is better than subclassing UINavigationController
for most cases.
I'm using iOS6 with a storyboard that includes a UINavigationController
set as the initial view controller.
//AppDelegate.m - this method is not available pre-iOS6 unfortunately
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;if(self.window.rootViewController){ UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject]; orientations = [presentedViewController supportedInterfaceOrientations];}return orientations;}
//MyViewController.m - return whatever orientations you want to support for each UIViewController
- (NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait;}
This answer relates to the questions asked in the comments of the OP's post:
To force a view to appear in a given oriention put the following in viewWillAppear:
UIApplication* application = [UIApplication sharedApplication];if (application.statusBarOrientation != UIInterfaceOrientationPortrait){ UIViewController *c = [[UIViewController alloc]init]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO];}
It's a bit of a hack, but this forces the UIViewController
to be presented in portrait even if the previous controller was landscape
UPDATE for iOS7
The methods above are now deprecated, so for iOS 7 use the following:
UIApplication* application = [UIApplication sharedApplication];if (application.statusBarOrientation != UIInterfaceOrientationPortrait){ UIViewController *c = [[UIViewController alloc]init]; [c.view setBackgroundColor:[UIColor redColor]]; [self.navigationController presentViewController:c animated:NO completion:^{ [self.navigationController dismissViewControllerAnimated:YES completion:^{ }]; }];}
Interestingly, at the time of writing, either the present or dismiss must be animated. If neither are, then you will get a white screen. No idea why this makes it work, but it does! The visual effect is different depending on which is animated.