Reputation: 6066
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
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
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