lviggiani
lviggiani

Reputation: 6066

iOS reset device orientation

Consider the following case: the iPhone is in portrait mode. I do this:

NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];

and lock my device orientation in landscape mode. So I can turn my phone in any direction and the orientation stays the same. Great;

Then I unlock orientation like this:

NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];

and device orientation will follow iPhone physical orientation as desired.

Now the problem comes with this case only: I set the orientation to landscape (UIInterfaceOrientationLandscapeRight) and keep the phone vertically (in portrait mode). The screen rotates as desired. Then I set orientation back to UIInterfaceOrientationUnknown without moving the phone... the screen stays in the landscape until I physically turn the phone horizontally and then back to a vertical position. So I need to tell the iPhone, other than unlocking the orientation, update screen orientation to device physical orientation (as happens automatically in Android for example). Is this possible? Finally: this happens at least on the iPhone simulator. I currently haven't a real device to test with.

Upvotes: 2

Views: 860

Answers (2)

Nischal Hada
Nischal Hada

Reputation: 3288

I have following example in Swift. Instead of using UIDeviceOrientation I foundUIApplication.shared.statusBarOrientation to be more reliable. I have more detail example in GitHub project

Declare

var currentInterfaceOrientation: UIInterfaceOrientation = UIInterfaceOrientation.unknown

Update orientation

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    coordinator.animate(alongsideTransition: { _ in
        if UIApplication.shared.statusBarOrientation.isLandscape {
            self.currentInterfaceOrientation = UIInterfaceOrientation.landscapeLeft
        } else {
            self.currentInterfaceOrientation = UIInterfaceOrientation.portrait
        }
        self.deviceDidRotate()
    })
}

private func deviceDidRotate() {
    //perform your action
    self.collectionView.reloadData()
}

Upvotes: 0

Gralex
Gralex

Reputation: 4485

You need subscribe to orientation change, and restore orientation when you need it. Here is full example:

@interface ViewController ()
@property (nonatomic, assign) BOOL fixedOrientation;
@property (nonatomic, assign) UIDeviceOrientation lastOrientation;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.fixedOrientation = false;
    [UIDevice.currentDevice beginGeneratingDeviceOrientationNotifications];
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(deviceOrientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)deviceOrientationChanged:(NSNotification *)notif {
    self.lastOrientation = [UIDevice.currentDevice orientation];
}

- (IBAction)buttPressed {
    UIDeviceOrientation last = [UIDevice.currentDevice orientation];

    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
    self.fixedOrientation = true;

    self.lastOrientation = last;
}

- (IBAction)butt2Pressed:(id)sender {
    self.fixedOrientation = false;
    NSNumber *value = [NSNumber numberWithInt:self.lastOrientation];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    if (self.fixedOrientation) {
        return UIInterfaceOrientationMaskLandscapeRight;
    }
    return UIInterfaceOrientationMaskAll;
}


@end

EDIT: requires fullscreen option shall be selected for both iPhone and iPad for this to work otherwise deviceOrientationChanged will never be called.

Upvotes: 2

Related Questions