Is [UIScreen mainScreen].bounds.size becoming orie

2018-12-31 16:36发布

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?

18条回答
泪湿衣
2楼-- · 2018-12-31 16:55

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.

查看更多
高级女魔头
3楼-- · 2018-12-31 16:56

Just adding the swift version of an excellent cbartel function answered above.

func screenSize() -> CGSize {
    let screenSize = UIScreen.mainScreen().bounds.size
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
        return CGSizeMake(screenSize.height, screenSize.width)
    }
    return screenSize
}
查看更多
梦醉为红颜
4楼-- · 2018-12-31 16:58

iOS 8 or upper

A solution for those who want to find out the screen size in points (3.5 inches screen has 320 × 480 points, 4.0 inches screen has 320 × 568 points, etc) would be

- (CGSize)screenSizeInPoints
{
    CGFloat width = [[UIScreen mainScreen] bounds].size.width;
    CGFloat height = [[UIScreen mainScreen] bounds].size.height;

    if (width > height) {
        return CGSizeMake(height, width);
    }
    else {
        return [[UIScreen mainScreen] bounds].size;
    }
}
查看更多
明月照影归
5楼-- · 2018-12-31 17:03

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
查看更多
初与友歌
6楼-- · 2018-12-31 17:05

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;
}
查看更多
梦寄多情
7楼-- · 2018-12-31 17:06

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
查看更多
登录 后发表回答