changing device orientation to landscape programmatically doesn't work - iphone

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];

Related

UINavigationController Force Rotate

My application is primarily portrait, however there is one view that REQUIRES a landscape orientation.
My views are contained within a UINavigationController, which (apparently) is the cause of this issue.
All UIViewControllers except one have this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
The UIViewController that requires Landscape has this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
Now, what happens is when the user reaches the landscape UIViewController, it is shown in portrait. The user can then rotate their phone and it displays in landscape as I want it to (locking to landscape). The user then progresses onwards to a portrait UIViewController and the same happens: it start in landscape, then they rotate their phone and it becomes portrait again (and locks to portrait).
It seems orientation locking is allowed between UIViewControllers, however auto-rotation / programmatically changing the orientation is somehow blocked.
How do I force the phone to update to the correct orientation?
There is a temporary solution: I can detect the orientation of the device and show a message asking them to rotate the device if it is not correct, however this is not optimal.
I had the same requirement for one of my applications!!!
luckily I found a solution!
In order to keep main viewcontroller landscape, no matter from what orientation it was popped/pushed, I did the following thing: (in viewWillAppear:)
//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];
P.S.Tested on sdk 3.2.5 ios 5.0.1.
P.S. On iOS 8 previous answer results some screen flickering and also - it is not stable (In some cases It does not work for me anymore.) So, for my needs, I changed the code to: (ARC)
//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
[self.navigationController presentViewController:[UIViewController new] animated:NO completion:^{
dispatch_after(0, dispatch_get_main_queue(), ^{
[self.navigationController dismissViewControllerAnimated:NO completion:nil];
});
}];
//I added this code in viewDidDissapear on viewController class, which will be popped back.
Hopefully it will help!
This might help. You can call the following method upon appearing, where appropriate. e.g. in -viewWillAppear:animated
attemptRotationToDeviceOrientation
Attempts to rotate all windows to the orientation of the device.
+ (void)attemptRotationToDeviceOrientation
Discussion
Some view controllers may want to use app-specific conditions to
determine the return value of their implementation of the
shouldAutorotateToInterfaceOrientation: method. If your view
controller does this, when those conditions change, your app should
call this class method. The system immediately attempts to rotate to
the new orientation. A rotation occurs so long as each relevant view
controller returns YES in its implementation of the
shouldAutorotateToInterfaceOrientation: method.
Availability
Available in iOS 5.0 and later.
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html
Use this,
[[UIDevice currentDevice]performSelector:#selector(setOrientation:) withObject:(__bridge id)((void *)UIInterfaceOrientationLandscapeRight)];

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

iPad launch orientation when flat on surface

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.

UIDevice currentDevice's "orientation" always null

As per the title.
Calling [[UIDevice currentDevice] BeginGeneratingDeviceOrientationNotifications] has no effect.
DidRotateToInterfaceOrientation etc events are working fine, but I need to be able to poll the device orientation arbitrarily.
How can I fix/do this?
The long story:
I have a tab application with a navigation controller on each tab. The root view of tab number one is a graph that goes full screen when the orientation changes to landscape; however this needs to be checked whenever the view appears as the orientation change could have occurred elsewhere, so I was hoping to poll the orientation state whenever this view appears.
UIDevice's notion of orientation seems to be only available on actual devices. The simulator seems to always return 0 here, regardless of whether the notifications have been enabled as the docs suggest. Irritatingly inconvenient, but there you go.
I find this works fine on the actual device:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
NSLog(#"orientation: %d", [[UIDevice currentDevice] orientation]);
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
seems like a silly question, but isn't it
beginGeneratingDeviceOrientationNotifications
( lower case b )
...
If you check [[UIDevice currentDevice] orientation] in - (void)viewDidLoad you will always get nil.
Check it in *- (void) viewDidAppear:(BOOL)*animated method and you
this is as per iMeMyself said in the comments above - this samed me a lot of time and I think is the right answer so I wanted to highlight it here:
UIDeviceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
//do stuff here
}
else if (UIInterfaceOrientationIsPortrait(interfaceOrientation))
{
//or do stuff here
}
Wouldn't [[UIDevice currentDevice] orientation] give you the current orientation state? You could check for this in your viewWillAppear method of the view controller that wants to poll.
Edit: Other than that, there are various ways to get the current orientation, such as using the statusBarOrientation property in UIApplication, or interfaceOrientation property in UIViewcontroller.

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?