iPad orientation returns unknown values - ipad

I use this code:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
to get iPad orientation but it returns UIDeviceOrientationUnknown when I use OpenGL rendering. When I play movies or I display UIViews it return the correct value. Do you know how may I get correct orientation? I don't want to use the accelerometer because I want to know when the device has locked orientation.
Thank you!

There are situations where the accelerometer can’t get an accurate read on the orientation, such as when the device is held flat. You should still be able to get the current orientation using:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

In iOS 13, the statusBarOrientation has been deprecated. The new preferred way of getting this orientation is
let orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation

If I add [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; the orientation will be correct even in OpenGL rendering mode. UIDeviceOrientationUnknown orientation is sometimes returned but only for short time.

Related

How can I refresh screen orientation in iOS

In my app, some ViewControllers should be shown in fixed orientation but the others are free to rotate screen orientation. When I fix orientation on some ViewController using
NSNumber *value = [NSNumber NumberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
and this lock orientation well. However, when I back to previous ViewController or move to other ViewController which is free to rotate, orientation does not get back to real orientation.
I just release orientation lock when ViewController moves on, but [[UIDevice currentDevice] orientation] only returns value which I set value, not current device's real orientation. [UIViewController attemptRotationToDeviceOrientation] didn't work also.
How can I get current device's real orientation and refresh layout?
Thanks in advance.

iOS 8 and UIScreen sizing issues

Our app consists of Cocos3D and AR. Since upgrading to iOS 8 we had to fix our orientation handling because of the changes Apple brought on us.
However, we still experience some issues that lead me to a rather interesting phenomena (I checked it in our app and in a fresh new project..):
Logging the [UIDevice currentDevice].orientation,[UIApplication sharedApplication].statusBarOrientation and [UIScreen mainScreen].bounds.size shows that when the device is rotated quickly, the device orientation actually changes, however the interface orientation sometimes stays the same and it leads to wrong calculations of the screen bounds... e.g.:
before rotation:
[UIDevice currentDevice].orientation = 1
[UIApplication sharedApplication].statusBarOrientation = 1
[UIScreen mainScreen].bounds.size = 414x736
after first rotation:
[UIDevice currentDevice].orientation = 4
[UIApplication sharedApplication].statusBarOrientation = 4
[UIScreen mainScreen].bounds.size = 736x414
after second rotation:
[UIDevice currentDevice].orientation = 1
[UIApplication sharedApplication].statusBarOrientation = 4
[UIScreen mainScreen].bounds.size = 736x414
Now obviously, after the second rotation, the device is back in portrait mode - well not according to the interface orientation and the screen bounds...
Am I missing something here?
I have had this issue in the past and have concluded that when you set up an observer to the UIDeviceOrientationDidChangeNotification the method you specify is called before all attributes change to reflect the new orientation. The way I dealt with it is to create a function which runs a block of code after a delay and then call:
- (void)deviceOrientationDidChange:(NSNotification *)note
{
RHRunBlockAfterDelay(0.5, ^{
// Execute relevant code...
});
}
The delay function is a wrapper around a call to [self performSelector:#selector(mySel) afterDelay:delay withObject:block]; defined in a separate Functions.h.

iOS Getting initial device orientation with accelerometer

I am working in an OpenGL ES game, c++ and iOS. I would like that the canvas axes be always as in default portait orientation, and also be able to know which is the initial device orientation and all the orientation changes.
The problem I have is that if I configure the XCode project to support the 4 orientations: 2 Portraits and 2 Landscapes, then the Frame which is embedded the OpenGL canvas has the axes depending the initial orientation. If I configure the project to support only Portrait Orientation, then the Application won't tell me if it is in Landscape.
I would like to find a way to do this as much programmatically as possible.
1) To Know programatically in iOS
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationLandscapeLeft)
landscapeRight = false;
else if(orientation == UIDeviceOrientationLandscapeRight)
else if(orientation == UIDeviceOrientationPortraitUpsideDown)
else if(orientation == UIDeviceOrientationPortrait)
....
2) For Default portrait view
Restrict other orientations in your Xcode project's info.plist

iOS5, iOS6, rotation, event firing arbitrarily

I have an app that supports orientation changes and rotates accordingly. I listen to the event UIApplicationWillChangeStatusBarOrientationNotification. Now during the load of this app I add some views and set them up in my app, based on the current orientation.
in iOS 6, this works fine and the app responds and rotates properly, so the user can load in both landscape and portrait mode and code works fine.
in iOS 5, if I load the app in portrait mode, the app works fine, and once that load has been completed in portrait mode, and the UI is aligned and sized, it will respond to other orientation changes to landascape or portrait. The problem I have is this : When loading iOS 5 in landscape mode, and while physically laying the device with iOS 5 on a flat surface to ensure its landscape, I get a OrientationNotification that moves from Landscape to portrait ( although the device didn't change ).
So another device iOS 6 in the same experiment, loads properly and I don't get any weird events of rotation changes that didn't occur, but with iOS 5 I do get them!!
Any ideas?
I am supporting the orientation for both iOS's
- (BOOL)shouldAutorotate {
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
It sounds like iOS 5 believes things should be portrait if, in fact, there is no physical orientation (i.e. flat up or down) and iOS 6 doesn't. For what it might be worth, to determine the orientation to display stuff when it matters, I use the actual device orientation when available and the status bar orientation when the device is flat. For instance:
// Get a useful screen orientation.
// If the device is physically in portrait or landscape then
// that is the orientation.
// If it is not, then it is probably flat on a table and use
// the orientation of the status bar which should be set to
// the last physical orientation.
//
// screen Orientation
//------------------------------------------------------------
+ (UIDeviceOrientation) screenOrientation {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation!=UIInterfaceOrientationPortrait
&& orientation!=UIInterfaceOrientationPortraitUpsideDown
&& orientation!=UIInterfaceOrientationLandscapeLeft
&& orientation != UIInterfaceOrientationLandscapeRight) {
// Not known at this time. Use the status bar orientation
orientation = [[UIApplication sharedApplication] statusBarOrientation];
}
return orientation;
}
I'm not sure that helps you directly, but perhaps in your notification handler you could check to see what the actual status bar orientation is. Or maybe the timing of the notification and the status-bar orientation change doesn't make that work.

Is it possible to find out if an app UI is in landscape orientation after a device has been set down on a surface?

I'm determining a frame offset for a keyboard if the user is holding iPad in landscape mode. I'm finding that I'm unable to properly set the offset if I'm adding content in landscape mode and then set the iPad flat on a surface. I'm using the code below to set the offset:
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft || [[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) {
tableView.frame = CGRectMake(0,0,tableView.frame.size.width, tableView.frame.size.height-keyboardsize.height);
}
UIDeviceOrientations that I can check for are:
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
(source: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html)
Is there any way for me to check/know if a user has been holding the app in landscape orientation (UIDeviceOrientationLandscapeLeft or UIDeviceOrientationLandscapeRight) and then set the device down (which should be UIDeviceOrientationFaceUp)
What you're interested in is not the device orientation, but the interface orientation. Try using self.interfaceOrientation (where self is your view controller). You can also get this from [[UIApplication sharedApplication] statusBarOrientation].
That being said, you probably shouldn't be using the interface orientation at all to find out where the keyboard is. The keyboard generates notifications when it appears and moves around, which include position information. Take a look at the UIKeyboardWillShowNotification and UIKeyboardWillChangeFrameNotification. They have position information in their userInfo dictionary under the UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey keys which will tell you where the keyboard will be.

Resources