.bounds.size在iOS8中变成取向依赖吗?

我在iOS 7和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); 

以下是iOS 8的结果:

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

与iOS 7中的结果相比:

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

有没有任何文件指定这个变化? 或者这是iOS 8 API中的一个临时性错误?

是的,这是取决于iOS8的方向,而不是一个错误。 您可以查看WWDC 2014中的会话214获取更多信息: “iOS 8中的视图控制器进步”

演讲报价:

UIScreen现在是面向接口的:

  • [UIScreen bounds]现在是面向接口的
  • [UIScreen applicationFrame]现在是面向接口的
  • 状态栏框架通知是面向接口的
  • 键盘帧通知是面向接口的

是的,它在iOS8中取决于方向。

我写了一个Util方法来解决这个需要支持旧版本操作系统的应用程序的问题。

 + (CGSize)screenSize { CGSize screenSize = [UIScreen mainScreen].bounds.size; if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { return CGSizeMake(screenSize.height, screenSize.width); } return screenSize; } 

是的,的确,屏幕大小现在取决于iOS 8的方向。然而,有时需要将大小固定为纵向。 这是我怎么做的。

 + (CGRect)screenBoundsFixedToPortraitOrientation { UIScreen *screen = [UIScreen mainScreen]; if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) { return [screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace]; } return screen.bounds; } 

是的,现在取决于方向。

我更喜欢下面的方法来获取屏幕尺寸的方向独立的方式上面的一些答案,因为它更简单,因为它不取决于任何方向代码(其状态可以依赖于时间,他们被称为)或版本检查。 您可能需要新的iOS 8行为,但是如果您需要在所有版本的iOS上保持稳定,这将会起作用。

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

与这个问题相关,因为它解决了我的问题,这里定义了我用于屏幕宽度和高度计算:

 #define SCREEN_WIDTH (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) : [[UIScreen mainScreen] bounds].size.width) #define SCREEN_HEIGHT (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) : [[UIScreen mainScreen] bounds].size.height) #define IOS_VERSION_LOWER_THAN_8 (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) 

如果您同时支持iOS 7和iOS 8,这是解决此问题的最佳解决方案。

这不是iOS 8 SDK中的错误。 他们界定了界面。 根据你对这个事实的一些参考或文档的问题,我强烈建议你观看View Controller Advancements in iOS 8它是从WWDC 2014开始的 214会话。 最有趣的部分(根据你的疑惑)是在50:45开始的Screen Coordinates

您可以使用nativeBounds (方向无关)

nativeBounds

物理屏幕的边界矩形,以像素为单位。 (只读)

声明SWIFT

  var nativeBounds: CGRect { get } 

该矩形基于纵向方向上的设备。 该值不随设备旋转而改变。

检测设备的高度:

 if UIScreen.mainScreen().nativeBounds.height == 960.0 { } 

检测设备的宽度:

 if UIScreen.mainScreen().nativeBounds.width == 640.0 { } 

是的,它在iOS8中取决于方向。

以下是如何以SDK和OS版本的iOS 8方式读取边界的一致方式。

 #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 

我的解决方案是MaxK和hfossli的组合。 我在UIScreen的一个类别上做了这个方法,它没有版本检查(这是一个不好的做法):

 //Always return the iOS8 way - ie 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; } 

我需要一个快速的帮助功能,保持与iOS7下的iOS7相同的行为 – 这使我[[UIScreen mainScreen] bounds]我的[[UIScreen mainScreen] bounds]调用,而不是触摸其他代码…

 + (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; } 

下面的方法可以用来查找给定方向的屏幕边界,独立于iOS版本。 此方法将根据设备的屏幕大小返回边界,并将独立于iOS版本提供相同的CGRect值。

 - (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation { CGFloat width = [[UIScreen mainScreen] bounds].size.width; CGFloat height = [[UIScreen mainScreen] bounds].size.height; CGRect bounds = CGRectZero; if (UIInterfaceOrientationIsLandscape(orientation)) { bounds.size = CGSizeMake(MAX(width, height), MIN(width, height)); } else { bounds.size = CGSizeMake(MIN(width, height), MAX(width, height)); } return bounds; } // For the below example, bounds will have the same value if you run the code on iOS 8.x or below versions. CGRect bounds = [self boundsForOrientation:UIInterfaceOrientationPortrait]; 

那就是我用来计算正确的矩形:

 UIScreen* const mainScreen = [UIScreen mainScreen]; CGRect rect = [mainScreen bounds]; #ifdef __IPHONE_8_0 if ([mainScreen respondsToSelector:@selector(coordinateSpace)]) { if ([mainScreen respondsToSelector:@selector(fixedCoordinateSpace)]) { id tmpCoordSpace = [mainScreen coordinateSpace]; id tmpFixedCoordSpace = [mainScreen fixedCoordinateSpace]; if ([tmpCoordSpace respondsToSelector:@selector(convertRect:toCoordinateSpace:)]) { rect = [tmpCoordSpace convertRect:rect toCoordinateSpace: tmpFixedCoordSpace]; } } } #endif 

只是添加上面的一个优秀的cbartel函数的迅捷版本。

 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 } 

我注意到的一件事情是,Info.plist中支持的接口方向的顺序很重要。 我用我的应用程序(即在代码中定位)得到了这个问题的问题,但是我没有指定任何地方,默认的方向是肖像。

我认为在任何情况下,默认的方向肖像。

在Info.plist中重新排列它,首先放置肖像,恢复预期的行为。

我的问题是相关的UIWindows帧正在减去。 所以在MyViewController – (NSUInteger)supportedInterfaceOrientations方法中做了下面的代码

 [[UIApplication sharedApplication] setStatusBarHidden:NO]; [self.view setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)]; [appDel.window setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)]; 

它的工作对我来说是尝试的。

这会在iOS7iOS8中给出正确的设备,

 #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) #define IS_PORTRAIT UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) + (BOOL)isIPHONE4{ // < iOS 8.0 if(SYSTEM_VERSION_LESS_THAN(@"8.0")){ if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) { return YES; } else { return NO; } // >= iOS 8.0 }else{ if(IS_PORTRAIT){ if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) { return YES; } else { return NO; } }else{ if ([self getDeviceWidth] == 480.0 && [self getDeviceHeight] == 320.0) { return YES; } else { return NO; } } } } + (BOOL)isIPHONE5{ // < iOS 8.0 if(SYSTEM_VERSION_LESS_THAN(@"8.0")){ if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) { return YES; } else { return NO; } // >= iOS 8.0 }else{ if(IS_PORTRAIT){ if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) { return YES; } else { return NO; } }else{ if ([self getDeviceWidth] == 568.0 && [self getDeviceHeight] == 320.0) { return YES; } else { return NO; } } } } + (BOOL)isIPHONE6{ // < iOS 8.0 if(SYSTEM_VERSION_LESS_THAN(@"8.0")){ if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) { return YES; } else { return NO; } // >= iOS 8.0 }else{ if(IS_PORTRAIT){ if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) { return YES; } else { return NO; } }else{ if ([self getDeviceWidth] == 667.0 && [self getDeviceHeight] == 375.0) { return YES; } else { return NO; } } } } + (BOOL)isIPHONE6Plus{ // < iOS 8.0 if(SYSTEM_VERSION_LESS_THAN(@"8.0")){ if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) { return YES; } else { return NO; } // >= iOS 8.0 }else{ if(IS_PORTRAIT){ if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) { return YES; } else { return NO; } }else{ if ([self getDeviceWidth] == 736.0 && [self getDeviceHeight] == 414.0) { return YES; } else { return NO; } } } } + (CGFloat)getDeviceHeight{ //NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height); return [UIScreen mainScreen].bounds.size.height; } + (CGFloat)getDeviceWidth{ //NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height); return [UIScreen mainScreen].bounds.size.width; } 

//你也可以添加更多的设备(ieiPad)。

iOS 8或更高版本

对于那些想要找出屏幕尺寸点(3.5英寸屏幕有320×480点,4.0英寸屏幕有320×568点等)的解决方案将是

 - (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; } } 

使用稍微修改的贫血症的解决方案,那一个没有iOS版本检查,在主屏幕边界使用最小/最大。
我需要一个CGRect所以得到CGRect从主界面,并改变了size.width=min(w,h)size.height=max(w,h) 。 然后我调用独立于操作系统的获取CGRect函数在我的代码中的两个地方,在那里我得到的OpenGL屏幕大小,触摸等。修复之前,我有2个问题 – 在横向模式的IOS 8.x显示位置的OpenGL视图是不正确的:左下角全屏的1/4。 而第二个接触返回无效的值。 这两个问题都解释如下。 谢谢!