iPad launch orientation when flat on surface - iphone

I have the following code:
-(void)viewWillAppear:(BOOL)animated {
UIDeviceOrientation orientation = [[UIDevice currentDevice] UIInterface];
if(orientation==UIDeviceOrientationLandscapeLeft || orientation==UIDeviceOrientationLandscapeRight) {
NSLog(#"Device Landscape");
} else {
NSLog(#"Device Portrait");
}
}
This works perfectly for the simulator and on the device but only if the iPad is not flat on a surface, for example if i lay the iPad on my desk and load the view it will say its portrait and so I cant detect the orientation when the view appears.
Any ideas of the best way to detect the interface orientation when the viewWillAppear is called?
Thanks

You should use [self interfaceOrientation] instead of the device orientation.

[[UIApplication sharedApplication] statusBarOrientation] also works if you are somewhere in the code that does not have access to [self interfaceOrientation]

First, do you know about the interfaceOrientation property of UIViewController? It looks like you are trying to duplicate it. If you really want to do that, simply subscribe to device orientation change notifications, check if the new orientation is valid interface orientation (the is a macro for that) and if yes, store the value to some variable (like lastSeenOrientation). Then you can rely on that value wherever you want.

Related

changing device orientation to landscape programmatically doesn't work

So I wam trying to forcefully change the device orientation at a part of my code by doing the following:
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait ||
[[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown){
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
}
however the orientation didn't change. Why is this? Basically the current orientation is portrait and I want it to be forced to be in landscape
If Inder Kumar Rathore's suggestion works, that's great. But the documentation describes the orientation property as being read-only, so if it works, I'm not sure you can rely on it working in the future (unless Apple does the smart thing and changes this; forcing orientation changes, regardless of how the user is currently holding their device, is such an obvious functional need).
As an alternative, the following code inserted in viewDidLoad will successfully (and somewhat curiously) force orientation (assuming you've already modified you shouldAutorotateToInterfaceOrientation as roronoa zorro recommended):
if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))
{
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
}
Clearly, this does it if the user is currently holding their device in portrait orientation (and thus presumably your shouldAutorotateToInterfaceOrientation is set up for landscape only and this routine will shift it to landscape if the user's holding their device in portrait mode). You'd simply swap the UIDeviceOrientationIsPortrait with UIDeviceOrientationIsLandscape if your shouldAutorotateToInterfaceOirentation is set up for portrait only.
For some reason, removing the view from the main window and then re-adding it forces it to query shouldAutorotateToInterfaceOrientation and set the orientation correctly. Given that this isn't an Apple approved approach, maybe one should refrain from using it, but it works for me. Your mileage may vary. But this SO discussion also refers to other techniques, too.
Works perfect on iOS7
If You want Potrait then:
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
if you want Landscape:
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationLandscapeRight]
forKey:#"orientation"];
There's no way you can force your device into portrait mode if it's in landscape and vice-versa.All you can do is tell your application to be in a particular mode either landscape or portrait.you can do that by:-
You should implement shouldAutorotateToInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Editing pList.
add a key UIInterfaceOrientation into your plist and change its property to UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight, UIInterfaceOrientationPortraitUpsideDown according to your needs..
Edit
This may not work in iOS 7 but it worked in previous versions of iOS, so downvoting this answer now doesn't make sense. The question was asked 2years ago and I answered it at that time and it was a working solution then.
[[UIDevice currentDevice] setOrientation: UIDeviceOrientationLandscapeLeft];

iPhone - getting device orientation in first view controller's view will appear

I've only one app delegate and view controller in my app.
The app works in both portrait and landscape modes.
In my view controller's viewWillAppear method I'm getting the orientation of the device usisng following code:
UIInterfaceOrientationIsPortrait([[UIDevice currentDevice] orientation])
First time when I am running the application, even when my device is in portrait, its giving the result as landscape.
Why is it so. How can I solve this?
I have had a ton of problems with currentDevice.orientation Try this:
UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation)
{
//LandscapeView
}
else
{
//PortraitView
}
From the documentation for UIDevice:
The value of this property always returns 0 unless orientation
notifications have been enabled by calling
beginGeneratingDeviceOrientationNotifications.
If you looked at the actual value being returned by 'orientation' you would see that it was 'UIDeviceOrientationUnknown'.

Device orientation - change in legal way (iOS 4.0+)

My app has navigation bar, where 1st screen returns YES to orientation, the second one is set to some orientation basing on what user choose in 1st screen. After going back to 1st screen from 2nd one, if user had device in hand in portrait but interface was in landscape, 1st screen is set to landscape. This happens because of
(BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation
Is called only after changing device orientation.
I want to check what is device orientation atm and set interface orientation to this one.
Tried:
//1st method:
UIViewController *rotateTheScreen = [[UIViewController alloc]init];
[self presentModalViewController:rotateTheScreen animated:NO];
[self dismissModalViewControllerAnimated:NO];
[rotateTheScreen release];
//2nd method:
UIInterfaceOrientation interfaceOrientation = self.interfaceOrientation;
//3rd method:
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
1st is acting strange, rotates all cases besides coming back from interface orientation = landscape and device orientation = landscape (here is a bug, he rotates to landscape)
2nd checks interface, like the name tells, and tho doesnt work for my problem
3rd as far as i heard is private and Apple rejects apps using this.
Take a look at this thread.
Basically, there's no way to force a device orientation and get your application approved by Apple.
Shortly, the method exists but is an undocumented method of the UIDevice class.
[[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight animated:YES];
This gives a compiler warning that you can get rid of with a category.
#interface UIDevice (MyAwesomeMethodsThatAppleWillNeverAllowMeToUse)
-(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
-(void)setOrientation:(UIInterfaceOrientation)orientation;
#end
Also, some say that you can call these methods indirectly using performSelector to get around Apple's static code analysis, as you can read in the comments here.
as I know there are no legal way. If I wrong, please, correct me somebody!
change the 'Initial interface orientation' in your project plist file

Inaccurate device orientation returned by UIDeviceOrientationDidChangeNotification

I'm listening to the UIDeviceOrientationDidChangeNotification in order to adjust my UI based on the device's orientation.
The problem is that the device orientation I'm getting from the notification seems inaccurate. If I start with the phone in portrait orientation and vertical (as if taking a picture with it) the orientation I get from the notification is correct. As the tilt of the phone approaches horizontal (as in laying flat on a table top) the orientation switches to landscape. This happens much before the phone is actually flat on the table. And this is without rotating the phone towards landscape at all. Is as if it had a preference for landscape.
When using other apps, like mail, I don't see this same behavior. It seems that mail only switches orientation once it's really sure you've gone to the new orientation.
Any help greatly appreciated.
Thanks,
I found my problem.
In viewWillAppear 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];
}
By checking that the orientation is one of the two landscapes or the two portraits I'm ignoring the UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown orientations. That way setting the phone in one of this two orientations won't have an effect on my interface's orientation.
My problem was that I was no considering the faceUp and faceDown and was handling them both in an else statement which was assuming landscape.
If your only interest is your interface orientation (ie landscape or portrait orientation of the device), you should NOT use UIDevice:orientation (or the UIDeviceOrientation* constants if you will), but rather use the UIApplication:statusBarOrientation, which uses the UIInterfaceOrientation* constants.
I use the following code to check for landscape modus:
static inline bool isOrientationIsLandscape() {
return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]);
}
And for portrait modus:
static inline bool isOrientationIsPortrait() {
return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]);
}
This cost me a whole morning to figure out, because there is no UIDeviceOrientationFace[Up|Down] on the simulator, only on the real device. So my app worked on the simulator all the time, but on the actual device I had some undefined behavoir during testing every now and then.
Now it works on the actual device like it does on the simulator.
HTH
The notifications are just one way to get at it, you can also read out the accelerometer yourself and implement it in exactly the way you see fit (with a delay and a certain time of non-rotation for example).
Don't know if it's a power drain to get those readouts, but if so, use the notification to know when things are moving, and then fire up the accelometer-reading.

iPhone SDK: Forcing landscape mode for a single part of an app

Yet another landscape mode question.
We've all seen the
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
Nonsense. I have not been able to get this to work on the simulator or on the device.
What I get is this:
http://i47.tinypic.com/zl9egh.png
when I really want this:
http://i45.tinypic.com/xms6cm.png
As you might be able to tell, it's flipping the phone but it's not realizing it has been flipped.
I've seen the hidden method
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
But I need this app to be on the app store, and I don't know if they will crack down on that.
Does anyone have any idea on how to get this damn thing to straighten itself out?
Ideally your view controller should implement:
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
Then the only allowed orientation for that view controller is one of the landscape orientations.
Unless you have a pretty complex view hierarchy that utilizes a tab bar controller, this should cause the view to rotate when it's pushed.
If it doesn't work you can try:
[[UIDevice currentDevice] performSelector:
#selector(setOrientation:)
withObject:(id)UIInterfaceOrientationLandscapeRight];
I have an app in the AppStore that uses this code because in my case I do have a complex hierarchy of views that keeps the one I need to be landscape only from working.
If you want to rotate a single part of the app you can use the CGAffineTransform transform property of a UIView. For an example check this thread:
How do I apply a perspective transform to a UIView?