24
votes

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
Try on a real device. Same problem?rmaddy
Unfortunately yes :(user3914418
iOS 8 does not use autorotate and orientation API's anymore, as far as I know. Each orientation change is just an animated bounds change.Legoless
Thanks for you comment Legoless, see my answer to mc01 please.user3914418
I see this same thing in a number of third party apps (Reeder for example).Stephen Darlington

8 Answers

16
votes

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
9
votes

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.

1
votes

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.

1
votes

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).
1
votes

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
0
votes

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?

0
votes

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

0
votes
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]];
        }
    }
}