Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force device rotation with +attemptRotationToDeviceOrientation failing

According to the UIViewController docs here,

https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

using [UIViewController attemptRotationToDeviceOrientation] forces the system to attempt to rotate the interface to a new orientation. I am attempting to force an interface rotation from portrait to landscape by:

  • setting a forceLandscape flag before attempting the rotation
  • Calling [UIViewController attemptRotationToDeviceOrientation]
  • implementing -supportedInterfaceOrientations in my view controller and checking a flag to change the supported orientations, e.g.

This forces -supportedInterfaceOrientations to be called again, which looks like

- (NSUInteger)supportedInterfaceOrientations {
    return self.forceLandscape ? UIInterfaceOrientationMaskLandscapeLeft : UIInterfaceOrientationMaskPortrait;
}

Even though -supportedInterfaceOrientations is being called and returns the new orientation, the interface does not rotate. I have confirmed that the project allows all orientations and that this view controller is the window's root view controller. Has anyone else run into this problem and found a solution? I am aware of all the hacks to fix this (presenting and dismissing modals, etc), but I would like a clean solution if possible. I have verified this issue on iOS 6 and 7.

Below is the complete code to reproduce:

@interface ALTViewController ()
@property (nonatomic, assign) BOOL forceLandscape;
@end

@implementation ALTViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

        self.forceLandscape = NO;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"button" forState:UIControlStateNormal];
    [button sizeToFit];
    [self.view addSubview:button];
    button.center = self.view.center;
    [button addTarget:self
               action:@selector(buttonPressed:)
     forControlEvents:UIControlEventTouchUpInside];
}

- (void)buttonPressed:(id)sender
{
    self.forceLandscape = YES;
    [UIViewController attemptRotationToDeviceOrientation];
}

- (NSUInteger)supportedInterfaceOrientations
{
    return self.forceLandscape ? UIInterfaceOrientationMaskLandscapeLeft : UIInterfaceOrientationMaskPortrait;
}
like image 531
alexshafran Avatar asked Oct 01 '13 20:10

alexshafran


2 Answers

A call to attemptRotationToDeviceOrientation only rotates the orientation of the interface, if and only if, the device itself has been rotated.

If your view controller only supported portrait orientation, for example, and the user rotated the device to landscape orientation, no interface rotation would occur. While the device was in landscape orientation, let's say your code toggles a flag which allows for landscape orientation. What would happen to the interface orientation? Nothing, because device orientation has already occurred. To get the interface orientation to match the device orientation, you would need to call attemptRotationToDeviceOrientation.

In my own code, I recently created a custom, multi-part view animation that didn't look right if interface rotation occurred in the middle of it. So I turned off interface rotation during the brief animation. If the user rotated the device during the animation, no interface orientation would occur. However, when interface orientation was turned back on, the interface would not rotate to match the device orientation until I called attemptRotationToDeviceOrientation.

like image 163
bilobatum Avatar answered Oct 06 '22 00:10

bilobatum


You could try to achieve something with: setStatusBarOrientation:animated: https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/occ/instm/UIApplication/setStatusBarOrientation:animated:

this fixed for me a similar issue.

like image 41
madprocessor Avatar answered Oct 05 '22 23:10

madprocessor