Inaccurate device orientation returned by UIDeviceOrientationDidChangeNotification

I am listening to UIDeviceOrientationDidChangeNotification to customize my user interface based on device orientation.

The problem is that the orientation of the device I receive from the notification seems inaccurate. If I start with the phone in portrait orientation and vertical (as if taking an image with it), then the orientation that I receive from the notification is correct. As the phone tilts closer to the horizontal (as when laying up on the table), the orientation switches to landscape. This happens much earlier than the phone actually stands on the table. And this does not turn the phone to the landscape. It looks like he prefers a landscape.

When using other applications, such as mail, I do not see the same behavior. It seems that the mail only switches orientation, as soon as it is really sure that you have switched to a new orientation.

Any help is greatly appreciated.

Thanks,

+4
source share
3 answers

If your interest is your interface orientation (i.e. landscape or device portrait orientation), you should NOT use UIDevice: orientation (or UIDeviceOrientation * constants, if you want), but rather use UIApplication: statusBarOrientation, which uses UIInterfaceOrientation * constants.

I use the following code to check landscape modus:

static inline bool isOrientationIsLandscape() { return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]); } 

And for portrait mode:

 static inline bool isOrientationIsPortrait() { return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]); } 

It cost me a whole morning to understand, because there is no UIDeviceOrientationFace [Up | Down], only on a real device. Thus, my application worked on the simulator all the time, but on the device itself from time to time I had some undefined behavior during testing.

Now it works on the device itself, as on a simulator.

NTN

+3
source

I found my problem.

In the WillAppear view, I have:

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(didChangeOrientation:) name: UIDeviceOrientationDidChangeNotification object: [UIDevice currentDevice]]; 

And here is the notification handler:

 - (void) didChangeOrientation: (id)object { UIInterfaceOrientation interfaceOrientation = [[object object] orientation]; //DLog(@"val is %i", interfaceOrientation); if (interfaceOrientation == UIDeviceOrientationLandscapeLeft || interfaceOrientation == UIDeviceOrientationLandscapeRight || interfaceOrientation == UIDeviceOrientationPortrait) { [self orientInterface:interfaceOrientation]; } 

While checking that the orientation is one of two landscapes or two portraits, I ignore the orientations UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown. Thus, setting the phone in one of these two orientations will not affect my orientation of the interface.

My problem was that I did not consider faceUp and faceDown and handled them as in the else statement, which suggested the landscape.

+9
source

Notifications are just one way to achieve this, you can also read the accelerometer yourself and implement it exactly as you see fit (for example, with a delay and a certain amount of non-rotation).

I don’t know if there is a power leak to get these readings, but if so, use a notification to know when something is moving, and then run the accelerometer.

+1
source

All Articles