分享

Is [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8?

 勤奋不止 2014-10-15

I ran the following code in both iOS 7 and iOS 8:

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL landscape = (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight);
NSLog(@"Currently landscape: %@, width: %.2f, height: %.2f", 
      (landscape ? @"Yes" : @"No"), 
      [[UIScreen mainScreen] bounds].size.width, 
      [[UIScreen mainScreen] bounds].size.height);

The following is the result from iOS 8:

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 568.00, height: 320.00

Comparing to the result in iOS 7:

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 320.00, height: 568.00

Is there any documentation specifying this change? Or is it a temporary bug in iOS 8 APIs?

share|improve this question
3  
Well the iOS8 output seems much more logical –  Levi Jun 10 at 20:40

10 Answers

up vote 58 down vote accepted

Yes, it's orientation-dependent in iOS8, not a bug. You could review session 214 from WWDC 2014 for more info: "View Controller Advancements in iOS 8"

Quote from the presentation:

UIScreen is now interface oriented:

  • [UIScreen bounds] now interface-oriented
  • [UIScreen applicationFrame] now interface-oriented
  • Status bar frame notifications are interface-oriented
  • Keyboard frame notifications are interface-oriented
share|improve this answer
    
Is this in documentation anywhere? The docs shipped with beta 5 seem to have wrong information in them. –  Hyperbole Aug 18 at 17:03
    
What is the best way to detect the orientation within an app extension? Follow up question is here: /questions/25830448/… –  barfoon Sep 14 at 6:48
    
It's in the iOS 8 final documentation. –  fabb Oct 2 at 17:42

Yes, indeed, screen size is now orientation dependent in iOS 8. Sometimes, however, it's desired to get a size fixed to portrait orientation. Here is how I do it.

+ (CGRect)screenBoundsFixedToPortraitOrientation {
    UIScreen *screen = [UIScreen mainScreen];

    if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
                    return [screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace];
    } 
    return screen.bounds;
}
share|improve this answer
1  
I'm finding that this fixes the problem with regular iPhone apps, but not with iPhone apps running on iPad. –  ThomasW Aug 21 at 1:11

Yes, it's orientation-dependent in iOS8.

I wrote a Util method to resolve this issue for apps that need to support older versions of the OS.

+ (CGSize)screenSize {
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        return CGSizeMake(screenSize.height, screenSize.width);
    } else {
        return screenSize;
    }
}
share|improve this answer
    
I edited the code please check, your condition for checking OS version was wrong –  Jageen Sep 1 at 12:22
    
@Jageen Please clarify, the version check works for me. What is the problem? –  cbartel Sep 2 at 22:06
    
What i understand is, we need to change height and width if OS is iOS8 and orientation is Landscape,, am I right ? –  Jageen Sep 3 at 4:03
    
@Jageen Negative, in iOS 8 the method is orientation-dependent. Your logic is switched. Your edit was correctly rejected. –  cbartel Sep 3 at 21:05
    
ohh in that case, i am wrong, thanks –  Jageen Sep 4 at 3:40
    
@cbartel is there a way to categorize this into UIScreen so that our original call to [UIScreen mainScreen].bounds.size will work for both iOS 7 and iOS 8? –  kevinl Sep 4 at 22:23
    
How can this be checked in an application extension? Don't have access to [UIApplication sharedApplication] –  barfoon Sep 14 at 6:48
    
shouldn't it be >= NS...IOS_7_1 then? –  obiwahn Oct 12 at 2:55
    
@obiwahn Negative, in iOS 8 the method is orientation-dependent. Your logic is switched. –  cbartel yesterday

It is not a bug in iOS 8 SDK. They made bounds interface oriented. According to your question about some reference or documentation to that fact I will highly recommend you to watch View Controller Advancements in iOS 8 it is 214 session from WWDC 2014. The most interesting part (according to your doubts) is Screen Coordinates which starts at 50:45.

share|improve this answer

Yes, it's orientation-dependent in iOS8.

Here's how you can have a concistent way of reading out bounds in an iOS 8 fashion across SDK's and OS-versions.

#ifndef NSFoundationVersionNumber_iOS_7_1
# define NSFoundationVersionNumber_iOS_7_1 1047.25
#endif

@implementation UIScreen (Legacy)

// iOS 8 way of returning bounds for all SDK's and OS-versions
- (CGRect)boundsRotatedWithStatusBar
{
    static BOOL isNotRotatedBySystem;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        BOOL OSIsBelowIOS8 = [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0;
        BOOL SDKIsBelowIOS8 = floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1;
        isNotRotatedBySystem = OSIsBelowIOS8 || SDKIsBelowIOS8;
    });

    BOOL needsToRotate = isNotRotatedBySystem && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
    if(needsToRotate)
    {
        CGRect screenBounds = [self bounds];
        CGRect bounds = screenBounds;
        bounds.size.width = screenBounds.size.height;
        bounds.size.height = screenBounds.size.width;
        return bounds;
    }
    else
    {
        return [self bounds];
    }
}

@end
share|improve this answer
1  
Checking the SDK version as well is a good tip in case colleagues are building your app with differing versions of the SDK (though that shouldn't be happening!). –  Craig McMahon Oct 9 at 14:26

Yes, it's now dependent on orientation.

I prefer the below method of getting the screen size in an orientation-independent way to some of the answers above, both because it's simpler and because it doesn't depend on any of the orientation code (the state of which can be dependent on the time that they are called) or on version checking. You may want the new iOS 8 behavior, but this will work if you need it to be stable on all versions of iOS.

+(CGSize)screenSizeOrientationIndependent {
     CGSize screenSize = [UIScreen mainScreen].bounds.size;
     return CGSizeMake(MIN(screenSize.width, screenSize.height), MAX(screenSize.width, screenSize.height));
}
share|improve this answer

I needed a quick helper function that kept the same behavior as iOS7 under iOS8 - this allowed me to swap out my [[UIScreen mainScreen] bounds] calls and not touch other code...

+ (CGRect)iOS7StyleScreenBounds {
    CGRect bounds = [UIScreen mainScreen].bounds;
    if (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        bounds.size = CGSizeMake(bounds.size.height, bounds.size.width);
    }
        return bounds;
}
share|improve this answer
    
Nasty, but gets the job done until time can be put into fixing things properly :-) –  DuneCat yesterday

One thing that I noted is, the order of supported interface orientations in Info.plist does matter. I got the problem of this question with my app (that does orientation in code), but I did not specify anywhere that default orientation is Portrait.

I thought that default orientation was Portrait in any case.

Rearranging itens in Info.plist, putting Portrait first, restored the expected behavior.

share|improve this answer

self.window frame is now depends on the device orientation.

That's why we are facing the bounds.size orientation issue.

To resolve this, http://iface2ios./2014/10/02/bounds-size-landscape-orientation-issue-in-ios-8-and-working-fine-in-ios-7/

share|improve this answer

My solution is a combination of MaxK's and hfossli. I made this method on a Category of UIScreen and it has no version checks (which is a bad practice):

//Always return the iOS8 way - i.e. height is the real orientation dependent height + (CGRect)screenBoundsOrientationDependent { UIScreen *screen = [UIScreen mainScreen]; CGRect screenRect; if (![screen respondsToSelector:@selector(fixedCoordinateSpace)] && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { screenRect = CGRectMake(screen.bounds.origin.x, screen.bounds.origin.y, screen.bounds.size.height, screen.bounds.size.width); } else { screenRect = screen.bounds; }

return screenRect;

}

share|improve this answer

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多