Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS 6 force device orientation to landscape

People also ask

How do you get landscape mode on iPhone 6?

Swipe down from the top-right corner of your screen to open Control Center. Tap the Portrait Orientation Lock button to make sure that it's off.

How do I force my iPad to landscape horizontally?

Make sure that Rotation Lock is off: Swipe down from the top-right corner of your screen to open Control Center. Then tap the Rotation Lock button to make sure it's off. Turn your iPad sideways.


Ok, folks, I will post my solution.

What I have:

  1. A view based application, with several view controllers. (It was navigation based, but I had to make it view based, due to orientation issues).
  2. All view controllers are portrait, except one - landscapeLeft.

Tasks:

  1. One of my view controllers must automatically rotate to landscape, no matter how the user holds the device. All other controllers must be portrait, and after leaving the landscape controller, the app must force rotate to portrait, no matter, again, how the user holds the device.
  2. This must work as on IOS 6.x as on IOS 5.x

Go!

(Update Removed the macros suggested by @Ivan Vučica)

In all your PORTRAIT view controllers override autorotation methods like this:

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

You can see the 2 approaches: one for IOS 5 and another For IOS 6.

The same 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 should add this:

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

Analogically, after you leave the LANDSCAPE controller, whatever controller you load, you should force again autorotation for IOS 5, but now you will use UIDeviceOrientationPortrait, as you go to a PORTRAIT controller:

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

Now the last thing (and it's a bit weird) - you have to change the way you switch from a controller to another, depending on the IOS:

Make an NSObject class "Schalter" ("Switch" from German).

In Schalter.h say:

#import <Foundation/Foundation.h>

@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end

In Schalter.m 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 the way you use Schalter ( suppose you go from Warehouse controller to 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 release instance_to_products object:

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

Well, this is it. Don't hesitate to downvote, I don't care. This is for the ones who are looking for solutions, not for reputation. Cheers! Sava Mazare.


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

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

I'm calling this before I'm pushing the next UIViewController. It will force the next pushed UIViewController to be displayed in Portrait mode even if the current UIViewController is in Landscape (should work for Portrait to Landscape too). Works on iOS 4+5+6 for me.


I think that best solution is to stick to official apple documentation. So according to that I use following methods and everything is working very well on iOS 5 and 6. In my VC I override following methods:

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

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

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

second one thats tells your VC which is preferred interface orientation when VC is going to be displayed.

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

Just change Portrait for orientation that you want ;) This solution is working smooth, I don't like the idea of creating macros and other stuff, that goes around this simple solution. Hope this help...


I had the same problem, 27 views in my application from which 26 in portrait and only one in all orientations ( an image viewer :) ). Adding the macro on every class and replace the navigation wasn't a solution I was comfortable with...

So, i wanted to keep the UINavigationController mechanics in my app and not replace this with other code.

What to do:

@1 In the application delegate in method didFinishLaunchingWithOptions

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 Because the navigationController will just responde with YES for autorotation we need to add some limitations: Extend the UINavicationController -> YourNavigationController and link it in the Interface Builder.

@3 Override the "anoying new methods" from navigation controller.

Since this class is custom only for this application it can take responsibility for it's 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;
}

I hope this will help you,


From the iOS 6 Release Notes:

Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate.

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


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

To fix it, I just added the preferredInterfaceOrientationForPresentation method in the 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;
}