IOS 6: landscape device orientation

I gave an application with support for 10 controllers. I use a navigation controller to load / unload.

All but one are in portrait mode. Suppose the 7th VC is in the landscape. I need it to be represented in the landscape when it loads.

Please suggest a way to get the orientation from portrait to landscape in iOS 6 (and will work well in iOS 5).

Here's how I did it BEFORE iOS 6:

- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; UIViewController *c = [[[UIViewController alloc]init] autorelease]; [self presentModalViewController:c animated:NO]; [self dismissModalViewControllerAnimated:NO]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return (interfaceOrientation == UIInterfaceOrientationPortrait); } 

The presentation and rejection of a modal VC caused the application to view its orientation, so shouldAutorotateToInterfaceOrientation received a call.

What I tried in iOS 6:

 - (BOOL)shouldAutorotate{ return YES; } -(NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskLandscape; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{ return UIInterfaceOrientationLandscapeLeft; } 

When loading, the controller remains in the portrait. After turning the device, the orientation changes only normally. But I need to make the controller automatically rotate to landscape when loading, so the user will have to rotate the device to correctly see the data.

Another problem: after turning the device back to portrait, the orientation goes to portrait, although I specified only in supportedInterfaceOrientations UIInterfaceOrientationMaskLandscape . Why is this happening?

In addition, NONE of the above 3 methods is called.

Some (useful) data:

  • In my plist file I specified 3 orientations - everything except the inverted one.
  • The project was launched in Xcode 4.3 IOS 5. All classes, including xibs, were created before Xcode 4.5 IOS 6, now I use the latest version.
  • In the plist file, the status bar is set to visible.
  • In the xib file (the one I want to be in the landscape) the status bar is "No", the orientation is set to landscape.

Any help is appreciated. Thank you

+56
objective-c iphone ios6 orientation
Sep 28 '12 at 13:22
source share
13 answers

Ok guys, I will post my decision.

What I have:

  • A view-based application with multiple view controllers. (It was navigation, but I had to do it based on a review due to orientation problems).
  • All view controllers are a portrait, except for one - landscapeLeft.

Tasks:

  • One of my view controllers should automatically rotate to landscape, regardless of how the user holds the device. All other controllers must be portraits, and after exiting the landscape controller, the application must be forced to rotate to the portrait, no matter again how the user holds the device.
  • This should work on both iOS 6.x and iOS 5.x

Go!

( Refresh Removed macros suggested by @Ivan Vučica)

In all of your PORTRAIT view controllers, override autorotation methods as follows:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ return (toInterfaceOrientation == UIInterfaceOrientationPortrait); } -(BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } 

You can see two approaches: one for iOS 5 and the other for iOS 6.

The same goes for your LANDSCAPE view controller with some additions and changes:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ [image_signature setImage:[self resizeImage:image_signature.image]]; return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft); } -(BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { [image_signature setImage:[self resizeImage:image_signature.image]]; return UIInterfaceOrientationMaskLandscapeLeft; } 

ATTENTION : to force autorotation in iOS 5 , you must add this:

 - (void)viewDidLoad{ [super viewDidLoad]; if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0) [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO]; } 

Similarly, after you leave the LANDSCAPE controller, no matter which controller you download, you must enable autorotation again for iOS 5, but now you will use the UIDeviceOrientationPortrait when you go to the PORTRAIT controller:

 - (void)viewDidLoad{ [super viewDidLoad]; if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0) [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO]; } 

Now the last one (and this is a bit strange) - you have to change the way you switch from controller to another, depending on iOS:

Make the NSObject class "Schalter" ("Switch" in German).

In Schalter.h they say:

 #import <Foundation/Foundation.h> @interface Schalter : NSObject + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease; @end 

At Schalter.m they say:

 #import "Schalter.h" #import "AppDelegate.h" @implementation Schalter + (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{ //adjust the frame of the new controller CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame]; CGRect windowFrame = [[UIScreen mainScreen] bounds]; CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height); VControllerToLoad.view.frame = firstViewFrame; //check version and go if (IOS_OLDER_THAN_6) [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view]; else [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad]; //kill the previous view controller [VControllerToRelease.view removeFromSuperview]; } @end 

NOW, this is how you use Schalter (assuming you're moving from a Warehouse controller to a Products controller):

 #import "Warehouse.h" #import "Products.h" @implementation Warehouse Products *instance_to_products; - (void)goToProducts{ instance_to_products = [[Products alloc] init]; [Schalter loadController:instance_to_products andRelease:self]; } bla-bla-bla your methods @end 

Of course you must free the instance_to_products object:

 - (void)dealloc{ [instance_to_products release]; [super dealloc]; } 

OK it's all over Now. Feel free to subvert, I don't care. This is for those who are looking for solutions, not for reputation. Hurrah! Sava Mazare.

+43
04 Oct '12 at 11:00
source share

This should work, similar to the pre-iOS 6 version, but with the UINavigationController :

 UIViewController *portraitViewController = [[UIViewController alloc] init]; UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController]; [self.navigationController presentModalViewController:nc animated:NO]; [self.navigationController dismissModalViewControllerAnimated:NO]; 

I call this until I click on the next UIViewController . This will cause the next UIViewController be displayed in portrait mode, even if the current UIViewController is in Landscape (should also work for Portrait to Landscape). Works on iOS 4 + 5 + 6 for me.

+34
Oct 01
source share

I think the best solution is to stick with the official documentation for Apple. Therefore, in accordance with this, I use the following methods, and everything works well on iOS 5 and 6. In my VC, I override the following methods:

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return UIInterfaceOrientationIsPortrait(interfaceOrientation); } 

Methods for iOS 6, the first method returns a supported orientation mask (as their name indicates)

 -(NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait; } 

the second one that tells your VC which is the preferred orientation of the interface when the VC will be displayed.

 - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } 

Just change the portrait for the orientation you want;) This solution works smoothly, I don’t like the idea of ​​creating macros and other things that cover this simple solution. Hope this help ...

+14
Nov 13 '12 at 11:39
source share

I had the same problem, 27 views in my application, of which 26 in the portrait and only one in all orientations (image viewer :)). Adding a macro to each class and replacing the navigation was not a solution that was convenient for me ...

So, I wanted to keep the UINavigationController mechanics in my application and not replace it with other code.

What to do:

@ 1 In the application delegate in the didFinishLaunchingWithOptions method

 if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0) { // how the view was configured before IOS6 [self.window addSubview: navigationController.view]; [self.window makeKeyAndVisible]; } else { // this is the code that will start the interface to rotate once again [self.window setRootViewController: self.navigationController]; } 

@ 2 Since navigationController will simply answer “YES” for autorotation, we need to add some restrictions: Extend UINavicationController → YourNavigationController and link it in the interface builder.

@ 3 Cancel the “new features” from the navigation controller.

Since this class is common only for this application, it can take responsibility for this controllers and respond in their place.

 -(BOOL)shouldAutorotate { if ([self.viewControllers firstObject] == YourObject) { return YES; } return NO; } - (NSUInteger)supportedInterfaceOrientations { if ([self.viewControllers firstObject] == YourObject) { return UIINterfaceOrientationMaskLandscape; } return UIInterfaceOrientationMaskPortrait; } 

Hope this helps you

+7
Oct 14
source share

From iOS 6 Release Notes :

Now, iOS containers (like UINavigationController) will not consult their children to determine if they should autorotate.

Does your rootViewController message down the ViewController hierarchy to your VC?

+3
Sep 28 '12 at 13:55
source share

I used the same method as OP pre-ios6 (present and reject modal VC) to show a single view controller in landscape mode (all the others in the portrait). It broke in ios6 with a VC landscape in the portrait.

To fix this, I just added the preferred InterfaceOrientationForPresentation method in landscape VC. Seems to work fine for os 5 and os 6 now.

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft); } - (BOOL)shouldAutorotate { return NO; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationLandscapeLeft; } 
+2
Feb 20 '13 at 2:08
source share

Hey guys, having tried many different possible solutions, without success, I came up with the following solution, hope this helps !.

I prepared the recipe :).

Problem: you need to change the orientation of viewcontrollers using navigationcontroller in ios 6.

Decision:

navigation suggested

step 1. one initial UIviewcontroler to launch modal segues in the landscape and portrait of UInavigationControllers as the image shows ....

deeper in UIViewController1 we need 2 segues actions on a global variable in Appdelegate ....

 -(void)viewDidAppear:(BOOL)animated{ if([globalDelegate changeOrientation]==0){ [self performSegueWithIdentifier:@"p" sender:self]; } else{ [self performSegueWithIdentifier:@"l" sender:self]; } } 

also we need a way back to portrait & | scenery....

 - (IBAction)dimis:(id)sender { [globalDelegate setChangeOrientation:0]; [self dismissViewControllerAnimated:NO completion:nil]; } 

step 2. The first clicked UiViewControllers on each NavigationController come with ...

 -(NSUInteger)supportedInterfaceOrientations{ return [self.navigationController supportedInterfaceOrientations]; } -(BOOL)shouldAutorotate{ return YES; } 

Step 3. We overwrite the supportedInterfaceOrientations method in a subclass of UInavigationController ....

in your customNavigationController we have .....

 -(NSUInteger)supportedInterfaceOrientations{ if([self.visibleViewController isKindOfClass:[ViewController2 class]]){ return UIInterfaceOrientationMaskPortrait; } else{ return UIInterfaceOrientationMaskLandscape; } } 

Step 4. On the storyboard or by code, set the FullScreenLayout checkbox to yes, both for portrait and landscape uinavigationcontrollers.

+2
Mar 07 '13 at 22:48
source share

Try switching to a UINavigationController that uses a category or is subclassed to indicate the desired orientation, and then navigate to the desired VC. More details here .

+1
Sep 28
source share

Alternatively, you can do the same using blocks:

 UIViewController *viewController = [[UIViewController alloc] init]; viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [self presentViewController:viewController animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }]; 

Also, call it before clicking on the new view.

+1
Nov 12 '13 at 2:20
source share

Browse to the Info.plist file and make changes enter image description here

0
Aug 02
source share

I had the same problem. If you want to make a particular view controller appear in landscape orientation, do it right before you insert it into the navigation stack.

 UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if (currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown) [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft]; UIViewController *vc = [[UIViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; [vc release]; 
0
Sep 17 '13 at 11:27
source share

I solved this by subclassing the UINavigationController and overriding the supported interface elements of the navigation controller as follows:

 - (NSUInteger)supportedInterfaceOrientations { return [[self topViewController] supportedInterfaceOrientations]; } 

All controllers implemented with support for built-in pointers with their desired orientations.

0
Feb 14 '14 at 23:08
source share

I used the following solution. In one view controller that has a different orientation than all the others, I added orientation checking in the prepareForSegue method. If the destination destination manager needs a different orientation of the interface than the current display, then a message is sent that causes the interface to rotate during synchronization.

 #import <objc/message.h> 

...

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)) { UIInterfaceOrientation destinationOrientation; if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]]) { UINavigationController *navController = (UINavigationController *)[segue destinationViewController]; destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation]; } else { destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation]; } if ( destinationOrientation == UIInterfaceOrientationPortrait ) { if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait ); } } } } 
-one
Jul 11 '13 at 17:01
source share



All Articles