UIInterfaceOrientaion not following app rules - xcode

I've been having a huge problem with this.
Xcode just simply turned my landscape mode app into a portrait view and It doesn't go back !
I've programmed the entire app almost to run in landscape mode in the Ipad.
On the Storyboard, every window is in lanscape.
I believe i did the settings correctly according to the images below
and finally on my viewController I have:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Anybody know what could be going wrong or why would Xcode just set the screen to portrait out of nowhere while I was just adjusting a viewController?

If you want to only support landscape then change shouldAutorotateToInterfaceOrientation to:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
return YES;
}
// Default
return NO;
}

Related

Landscape views only loading properly from portrait and after rotating, why?

new iOS developer here. I have multiple views that require different images to be displayed in portrait and landscape. I currently have implemented that successfully and the portrait image loads fine, and, upon rotation, the landscape image also loads fine. However, if the device is in landscape orientation then switches to another view, it loads improperly - wrong size, resolution, alignments, etc. My code for dealing with orientation changes is below:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if((self.interfaceOrientation == UIDeviceOrientationLandscapeLeft) || (self.interfaceOrientation == UIDeviceOrientationLandscapeRight))
{
_image1.image = [UIImage imageNamed:#"Landscape.png"];
}
else if((self.interfaceOrientation == UIDeviceOrientationPortrait) || (self.interfaceOrientation == UIDeviceOrientationPortraitUpsideDown))
{
_image1.image = [UIImage imageNamed:#"Portrait.png"];
}
}
I believe it is because the method is only called upon rotation. If I rotate the improper, initial landscape view, for instance, it displays the correct images once again. Is there a way to get the method to run and load the proper landscape view when the initial orientation is in landscape? Or a way to force the correct image to display? Thanks much.
I finally fixed this issue by adding an orientation checker. I added the following in my .h:
#property (nonatomic, readonly) UIDeviceOrientation *orientation;
Then I added this to my .m file in the viewDidLoad method:
if(([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) {
_image1.image = [UIImage imageNamed:#"Landscape.png"];
}
This checks if the initial orientation is landscape. If it is, it loads my Landscape.png image. Otherwise, since the default image is my Portrait.png, as set in the Storyboard, that loads if the orientation is already in portrait. Cheers!
EDIT: The above code is not advised as you can run into issues when using it, such as with orientation-locked devices. I changed the it to check for the status bar's orientation, rather than the device's orientation, as below:
if(([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft) ||
([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight)) {
_image1.image = [UIImage imageNamed:#"Landscape.png"];
}
You do not need to declare any variables in the .h, and just add the above in the viewDidLoad method.

How to rotate the view in iOS5?

I have used a splitviewController in my application. The orientation of the app is strictly set to landscape. I have done it properly in the build settings.
When I run my app in iOS 5.1 or greater, it works nicely. But when I run my app in iOS 5 or less, the orientation of the app is not changed to landscape. It's a big problem. Is there any solution?
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Use this in all viewControllers for orientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
[super shouldAutorotateToInterfaceOrientation:interfaceOrientation];
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
Easy. Insert the following instead:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
You should replace your
return (interfaceOrientation == UIInterfaceOrientationPortrait);
statement with
return ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));

IOS6: Size of View in Landscape

just updated to IOS SDK 6 and now I'm confused. Tried to find a solution but I failed.
Created a new "Single View iPad APP" (I have an iPad 3) in xcode
Disabled Portrait & Upside-Down interface orientations in TARGETS->Summary
Set simulated metrics "orientation" to "Landscape"
Added following lines of code into the view controller file:
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"%#", NSStringFromCGRect(self.view.frame));
}
Run APP
My output is: 2012-10-09 18:18:40.149 TestApp[6165:907] {{20, 0}, {748, 1024}}
Does anybody know why the frame is not ... {{0, 20}, {1024, 748}} as I would expect? Maybe I missed something!
Thank you!
I don't think you missed anything, but if you wrap your view controller with a UINavigationController, the frame will be set as expected.
NB: With the iOS 6 SDK, you can no longer combine any of the UIInterfaceOrientation constants as a mask. So you need:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
That doesn't explain the issue, though, since preferredInterfaceOrientationForPresentation is not called when a view controller is the root controller of a UIWindow.

Portrait and Landscape mode in iOS6

When updating my app to iOS6 standard the portrait / landscape is gone. Ir worked perfectly when I was building with Xcode 3. But now using latest Xcode and latest SDK the rotation is gone and it is always in portrait mode. No matter what I put in "Supported interface Orientations". And the code I used to get rotation before seems to have no effect at all.
I had these lines.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
return YES;
default:
return NO;
}
}
How do I change and what do I change to get it work again?
First of all, in AppDelegate, write this. THIS IS VERY IMP
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return (UIInterfaceOrientationMaskAll);
}
Then, For UIViewControllers, in which you need only PORTRAIT mode, write these functions
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait);
}
For UIViewControllers, which require LANDSCAPE too, change masking to All.
- (NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskAllButUpsideDown);
//OR return (UIInterfaceOrientationMaskAll);
}
Now, if you want to do some changes when Orientation changes, then use this function.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
EDIT :
A lot depends on with which controller is your UIViewController embedded in.
Eg, If its inside UINavigationController, then you might need to subclass that UINavigationController to override orientation methods like this.
subclassed UINavigationController (the top viewcontroller of the hierarchy will take control of the orientation.) did set it as self.window.rootViewController.
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
From iOS 6, it is given that UINavigationController won't ask its UIVIewControllers for orientation support. Hence we would need to subclass it.
How to support one or more landscape controllers in app that is portrait mainly in ios6:
1) in AppDelegate
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UINavigationController* ns = (UINavigationController*)self.window.rootViewController;
if (ns) {
UIViewController* vc = [ns visibleViewController];
//by this UIViewController that needs landscape is identified
if ([vc respondsToSelector:#selector(needIos6Landscape)])
return [vc supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait; //return default value
}
2) in UIView controller(s) that needs landscape (or portrait+lanscape etc):
//flag method
-(void)needIos6Landscape {
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
3) in controllers, to which you can RETURN from controllers, that can be rotated in landscape - this is important, otherwise they remaind landscape on return from landscape-enabled VC.
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
4) (maybe not needed, but for sure..) - subclass navigation controller(s) you using, and add:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
UIViewController* vc = [self visibleViewController];
if (vc) {
if ([vc respondsToSelector:#selector(needIos6Landscape)]) {
return [vc supportedInterfaceOrientations];
}
}
return UIInterfaceOrientationMaskPortrait;
}
The important step is to ask for orientation only controllers from your app, because during transition between controllers, for some time there is some system controller as root, and will return incorrect value (this took me 2 hrs to find out, it was reason it was not working).
Don't know whether your issue was alike but with me, the status bar was oriented correctly (landscape) and the UIViewController was portrayed.
I changed following line in the application delegate application:didFinishLaunchingWithOptions:
//[window addSubview:navigationController.view];
self.window.rootViewController = navigationController;
Apple=> this costed me a day and a half to find out, and a lot of money!!!

iPad: How to display a different screen depending on orientation (landscape / portrait)

I have an iPad application that can be used in all four view modes (portrait up/down and landscape left/right). But at a certain point I have a View that I only want to be seen in landscape mode. So I do the following in the UIViewController that will trigger the action to view the landscape-only view:
- (void) showProperty:(Property *) property {
if ([self interfaceOrientation] == UIInterfaceOrientationLandscapeLeft || [self interfaceOrientation] == UIInterfaceOrientationLandscapeRight) {
PropertyViewController *propertyView = [[PropertyViewController alloc] initWithNibName:#"PropertyViewController" bundle:[NSBundle mainBundle]];
propertyView.property = property;
[self.navigationController pushViewController:propertyView animated:YES];
[propertyView release];
propertyView = nil;
}
else {
RotateDeviceViewController *rotateView = [[RotateDeviceViewController alloc] initWithNibName:#"TabRotate" bundle: [NSBundle mainBundle]];
rotateView.property = property;
[self.navigationController pushViewController:rotateView animated:YES];
[rotateView release];
rotateView = nil;
}
}
This works fine and thus shows either the desired screen (PropertyViewController) when the iPad is held in landscape mode, and if not it shows the RotateDeviceViewController which shows the user a message that he/she is supposed to rotate the device to correctly view the screen.
So when the user then rotates his/her device to landscape mode I want to show them the right view (PropertyViewController). And all of this kinda works!
The problem arises though in this RotateDeviceViewController.. There I have the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
[self showProperty];
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
- (void) showProperty {
PropertyViewController *propertyView = [[PropertyViewController alloc] initWithNibName:#"PropertyViewController" bundle:[NSBundle mainBundle]];
propertyView.property = property;
[self.navigationController pushViewController:propertyView animated:YES];
[propertyView release];
}
So as soon as I rotate the device (when viewing the RotateDeviceViewController) to landscape mode I show the user the PropertyViewController. This works... But when the PropertyViewController appears it shows my layout 90 degrees rotated. So basically it shows the content in portrait mode instead of using the landscape mode (which is actually the way you are holding the device)..
I hope this makes sense and someone can show me what's causing this.
Screenshots to make it more clear:
When device is held in portrait mode
After rotating the device
At this point
- (BOOL)shouldAutorotateToInterfaceOrientation:UIInterfaceOrientation)interfaceOrientation
You are telling the view controller what orientations you support. The device has not actually rotated yet therefore the view controllers intefaceOrientation property will still be portrait so when it is pushed onto the stack it thinks the device is portrait.
pseudo code
shouldAutoRotate... // at this point self.interfaceOrientation == portrait
// you push your controller here so it loads when the property is
I'm not sure if this will work well but the earliest I can see you can push is in
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

Resources