UIDevice.current.orientation report wrong value - ios

I locked my view in portrait, but for some reason I need to know the actual device orientation, The UIDevice.current.orientation as documentation is saying in description Returns the physical orientation of the device. this var sometimes works well and return real device orientation and sometimes return protrait (which is wrong, because I rotated the device to landscape). So I expect to get real device orientation (despite I locked my view to portrait), is it a wrong expectation? If not why this inconsiste behavior is happening?
Note: I tried UIDevice.current.endGeneratingDeviceOrientationNotifications(), the result is the same.

when portrait orientation lock is on, UIDevice.current.orientation always return .up
so, use motion instead:
iOS device orientation disregarding orientation lock

Related

Get "locked orientation", also known as "view orientation"

I have locked the orientation via XCode to be either landscape-left and landscape-right, but using UIDevice.current.orientation is giving the orientation as if it was not locked. Like when I am physically (in real life) in portrait, but my view is locked in landscape-left, I want to still get landscape-left, is this possible?
I can of course get the non-specific orientation by testing if width > height. But i needed the specific orientation of either landscape-left or -right.
Instead of asking the device for its orientation, ask the app for its orientation, by asking for UIApplication.shared.statusBarOrientation.

Check the app orientation in iOS (not the device orientation)

Until now, I used to use this code to check if my device is in a portrait or landscape mode:
if (UIDeviceOrientationIsPortrait(UIDevice.current.orientation)){
//portrait
}else {
//landscape
}
But I discovered that this variable check the real position of the device in the 3D space. So if my iPad or iPhone is in a portrait mode and I put it on a table, parallel to the ground, the orientation will not be considered as portrait.
Is there a variable or something similar that can I check to know the orientation of the app and not the physical orientation?
Use UIApplication.shared.statusBarOrientation: The current orientation of the app's status bar.

Programmatically disable portrait orientation lock

In my camera app, everything works perfectly fine orientation wise. If portrait orientation lock is not enabled on a users phone, then everything works perfectly.
However, if a user has portrait orientation lock enabled and they record sideways, then the video gets recorded in portrait mode but everything is sideways inside the video.
Is there any way to check if portrait orientation lock is enabled or any way to get around this? Thank you.
There are a couple of things. You can override the shouldAutorotate function in the view controller that you are using the camera in like so:
override func shouldAutorotate() -> Bool {
return true
}
Then you could set it to false again once they are finished with the camera so it retains their device settings. Not sure if this is the best way, but is A way.
Another possible way that you might be able to get around this is to simply always check the device orientation. The device will still detect the physical orientation of the device even if the visual orientation of the UI doesn't autorotate (https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation). So the following shows the possible device orientations, as per the Apple documentation (https://developer.apple.com/documentation/uikit/uideviceorientation)
enum UIDeviceOrientation : Int {
case Unknown
case Portrait // Device oriented vertically, home button on the bottom
case PortraitUpsideDown // Device oriented vertically, home button on the top
case LandscapeLeft // Device oriented horizontally, home button on the right
case LandscapeRight // Device oriented horizontally, home button on the left
case FaceUp // Device oriented flat, face up
case FaceDown // Device oriented flat, face down
}
Knowing those you can just check if the current orientation is one of those:
if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft ||
UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft) {
...override autorotate to true
}
These might solve your issue.
You can disable portrait orientation lock by using this method:
- (NSUInteger)lockorientation
{
return UIInterfaceOrientationMaskPortrait;
}

shouldAutorotateToInterfaceOrientation gets called but app interface does not reorients (only the status bar reorients)

I am trying to build an app that only works for landscape device orientations on iOS devices. That means my shouldAutorotateToInterfaceOrientation returns true for only landscape device orientations. However at some points of time, I need to switch to portrait device orientation for which I use setStatusBarOrientation API.
After holding the device in any landscape orientation and setting the interface orientation to default/upside down by using setStausBarOrientation API, and just tilting the device slightly in the held orientation orientation only, the status bar rotates but the interface does not rotates. shouldAutorotateToInterfaceOrientation does get called and returns true but still interface does not reorient. Also, problem gets solved if I rotate the device in opposite orientation. I am not sure what I am doing wrong.
Apple have accepted this as a bug in their SDK and they might fix the issue in the next release.

Determining the Orientation of the screen rather than the orientation of the device

The [[UIDevice currentDevice] orientation] method returns a number of orientations beyond the portrait and landscape orientation. I am well aware of checking to see if the orientation returned is "valid", unfortunately if the orientation returned is NOT "valid" when my app requires a specific orientation to determine which methods to run, I have no way of knowing which method is appropriate.
I have attempted a number of solutions to this, but for now the only thing I have been able to work out is to check to see if the orientation is LandscapeLeft or LandscapeRight and if it isn't I assume the screen is in portrait orientation. Unfortunately this isn't true when the device is face up and the screen is in landscape orientation.
I attempted to use the parent view controller's orientation:
parentController.interfaceOrientation;
Unfortunately it returned UIDeviceOrientationUnknown. I search SO and Google for someone else who has faced this problem. It seems silly to me that Apple would have anything but LandscapeLeft/Right and PortraitUp/Down for their orientations.
What I really need is the APPS orientation not the devices, since these are sometimes at odds. Any advice?
Have you tried using UIInterfaceOrientationPortrait/UIInterfaceOrientationLandscape? I usually have pretty good results using these methods:
if(UIInterfaceOrientationIsPortrait(viewController.interfaceOrientation)) {
//do portrait work
} else if(UIInterfaceOrientationIsLandscape(viewController.interfaceOrientation)){
//do landscape work
}
You might also try UIDeviceOrientationIsValidInterfaceOrientation.
These will only return the app's orientation, which may not be the same as the device's orientation.
If those don't work, you can also try:
[[UIApplication sharedApplication] statusBarOrientation]

Resources