24

my app up to iOS 7 works correctly. I tried it today with Xcode 6 and when I run it I have a nasty surprise :(:

enter image description here You can see that Xcode now draw my viewController as if it is in portrait mode but as you can see is in landscape mode.

Do you know what is changed in iOS 8? :/ I used the following orientation methods:

  • (NSUInteger)supportedInterfaceOrientations
  • (BOOL)shouldAutorotate
  • (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

EDIT:

I just discover this method:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 
{
 return UIInterfaceOrientationMaskLandscape;
}

And now my first viewcontrollers works correctly :). the problem is when I show a modal (that change the set of method in UIInterfaceOrientationMaskAll) remake the ugly effect of screenshot. Precisely i change my methods in this mode:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if(self.restrictRotation)
    {
        return UIInterfaceOrientationMaskLandscape;
    }    
    else
    {
        return UIInterfaceOrientationMaskAll;
    }
}


// THIS IS A DELEGATE OF MODAL VIEW CONTROLLER
- (void)updateInterfaceAfterDocumentPreviewViewController
{
    NSLog(@"updateInterfaceAfterDocumentPreviewViewController");

    [[UIApplication sharedApplication]     setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];

    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    appDelegate.restrictRotation = YES;
}

8 Answers8

16

Please try the following code

In the didFinishLaunchingWithOptions of AppDelegate

self.window.rootViewController = self.viewController;

[self.window makeKeyAndVisible];

[self.window setFrame:[[UIScreen mainScreen] bounds]]; //Add
Hitesh
  • 3,449
  • 8
  • 39
  • 57
chonbo
  • 261
  • 1
  • 3
9

The issue seems to be the order of calls when you set up the window. You need to call makeKeyAndVisible before you assign the rootViewController in your didFinishLaunchingWithOptions method on the app delegate. The following works:

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
[self.window makeKeyAndVisible];
self.window.rootViewController = self.myMainViewController;

But if you change the order to:

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = self.myMainViewController;
[self.window makeKeyAndVisible];

You get the behavior you are experiencing.

Dave Kammeyer
  • 369
  • 2
  • 8
1

I had the same exact problem with a "Loading screen". This is what worked for me. (Please note: my App only supports iOS 7 or later, landscape mode.) :

    CGRect theFrame = self.view.frame;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
        CGRect screenBounds = [[UIScreen mainScreen] bounds];
        theFrame.origin = CGPointZero;
        theFrame.size.width = screenBounds.size.height;
        theFrame.size.height = screenBounds.size.width;
    }

    NSLog(@"%@", [NSNumber valueWithCGRect:theFrame]);
    self.loadingScreen = [[UIView alloc] initWithFrame:theFrame];

Please refer to Mike Hay's answer if your App supports portrait orientation and for the "long way to calculate the correct applicationFrame": https://stackoverflow.com/a/18072095/4108485

Hope this helps.

Community
  • 1
  • 1
l3bel
  • 81
  • 2
  • 6
1

Have a look at your .plist file.

  1. Make sure you have "Initial interface orientation" set as the orientation you wanted.
  2. In the "Supported interface orientations", have the preferred orientation as the first entry on the list (looks like apple changed this order).
benaneesh
  • 426
  • 6
  • 10
1

I was having a similar problem, I couldn't get the right Launch Images to show (I had two for iPad, Default-Portrait.png and Default-Landscape.png) and I also couldn't get the App itself to auto orient after the Launch Image disappeared.

To solve the problem for the Launch Images:

  • Go to the Custom iOS Target Properties section of the project (Click on your Project's Icon at the top of the list of project files, and it should be the first section you see).
  • Add a row to that table called "Launch image" (should autofill) and enter "Default" as the string in the right column.
  • Make sure your Launch Images follow Apple's filename guidelines (ie: Default-568@2x, Default@2x, etc) check this SO answer

To solve the app orientation issue at first ViewController:

  • Go to your projects plist file (should be "YourApp-Info.plist")
  • Add a row and enter "Supported interface orientations"
  • Add the orientations that your app supports
Community
  • 1
  • 1
a.scarlett
  • 77
  • 1
  • 9
0

That approach to detecting orientation was deprecated in iOS8 (but still allowed for now). It was replaced with the concept of Size Classes and Trait Collections.

(Oddly, I can't seem to find a Size Class Reference in Apple's docs online right now - would swear it was there before - maybe in XCode). See here for WWDC videos.

Anyway, there's a checkbox in Interface Builder that says "Use Size Classes." Could be you have that checked. Turn it off & see if that helps?

Community
  • 1
  • 1
mc01
  • 3,750
  • 19
  • 24
  • Nothing change :(. In my opinion it is a problem of UIWindow because if I set backgroundColor of my view I see always the black color of UIWindow. Also if I print the window's frame... it's correct –  Sep 15 '14 at 17:56
  • Hmm. Does it stay that way when you change simulator orientation between landscape & portrait? Or is it only when it starts running? Are you using Auto Layout? Maybe some constraint is to blame? – mc01 Sep 15 '14 at 18:04
  • 1
    I don't use auto layout in this project, if I run the application in landscape mode the application works correctly, instead if I run the application in portrait mode the application is showed like the screenshot attached (has to be showed in landscape). If I change the device orientation in info.plist and put only landscape it works but I need also portrait to show a qlpreviewcontroller in both the orientations. –  Sep 15 '14 at 18:08
0

Oldschool solution:

BOOL portrait;
BOOL iOS8OrLater = ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0);
if (iOS8OrLater) {
    CGFloat height = CGRectGetHeight(self.view.frame);
    CGFloat width = CGRectGetWidth(self.view.frame);
    if (width / height > 1.0) {
        portrait = NO;
    } else {
        portrait = YES;
    }
} else {
    portrait = UIInterfaceOrientationIsPortrait(self.interfaceOrientation);
}
if(portrait) {
    [self layoutPortrait];
} else {
    [self layoutLandscape];
}

You can call this in viewWillLayoutSubviews

Avi Cohen
  • 3,102
  • 2
  • 25
  • 26
0
UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;

if( UIDeviceOrientationIsLandscape( currentOrientation ) )
{
    if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
    {
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

        // -- Fix for rotation issue for ios 8
        if( IS_IOS_8_OR_LATER )
        {
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPad"
                                                                 bundle: nil];
            // -- Set frame of nav controller
            UINavigationController *nc = [storyboard instantiateViewControllerWithIdentifier:@"NavController"];

            self.window.rootViewController = nc;

            [self.window setFrame:[[UIScreen mainScreen] bounds]];

            // -- Set fame of home view controller
            UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"Home"];

            self.window.rootViewController = vc;

            [self.window makeKeyAndVisible];

            [self.window setFrame:[[UIScreen mainScreen] bounds]];
        }
    }
}