在 iOS8中,[ UIScreenmainScreen ] . bound. size 是否变得依赖于方向?

我在 iOS7和 iOS8中都运行了以下代码:

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);

以下是 iOS8的结果:

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

与 iOS7的结果相比:

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

是否有任何文档说明这一变化? 或者这只是 iOS8API 中的一个临时 bug?

89037 次浏览

是的,它是依赖于 iOS8的方向,而不是 bug。你可以从 WWDC 2014的214会议中查看更多信息: “ iOS8中查看控制器的进步”

引用演讲中的话:

UIScreen 现在面向界面:

  • [ UIScreen 界限]现在面向接口
  • [ 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;
}

它不是 iOS8SDK 中的 bug。根据你的问题,一些参考或文件的事实,我会强烈建议你观看 View Controller Advancements in iOS 8它是214届从 WWDC 2014。最有趣的部分(根据你的怀疑)是 Screen Coordinates在50:45开始。

是的,实际上,现在 iOS8的屏幕大小取决于方向。然而,有时候,人们希望得到一个固定的大小,以纵向方向。我是这么做的。

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


if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
return [screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace];
}
return screen.bounds;
}

是的,在 iOS8系统中这是取决于方向的。

这里介绍了如何以一种一致的方式,以 iOS8的风格读取 SDK 和 OS 版本的界限。

#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

是的,现在取决于方向。

比起上面的一些答案,我更喜欢下面这种方法,因为它更简单,而且不依赖于任何方向代码(其状态可以取决于调用它们的时间)或版本检查。您可能想要新的 iOS8行为,但这将工作,如果您需要它是稳定的所有版本的 iOS。

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

我注意到,Info.plist 中支持的接口方向的 秩序确实很重要。我在我的应用程序中遇到了这个问题(它在代码中进行定向) ,但是我没有在任何地方指定默认的定向是 Portrait。

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

在 Info.plist 中重新排列项,将 Portrait 放在第一位,恢复了预期的行为。

我需要一个快速的 helper 函数,它能够保持 iOS8下 iOS7的相同行为——这使我能够交换掉我的 [[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;
}

我的解决方案是 MaxK 和福斯利的结合。我在 UIScreen 分类中创建了这个方法,它没有版本检查(这是一个不好的做法) :

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

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

#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)

如果您同时支持 iOS7和 iOS8,这是解决这个问题的最佳方案。

这就是我用来计算正确正误的方法:

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

下面的方法可以用来查找给定方向的屏幕边界,与 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];

只是增加了一个优秀的卡特尔功能的快速版本回答了上述问题。

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
}

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

原生界限

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

声明 SWIFT

  var nativeBounds: CGRect { get }

此矩形基于设备的纵向方向 值在设备旋转时不变。

检测设备的高度:

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


}

检测设备的宽度:

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


}

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

我的问题与 UIWindows 框架有关,它是负数。 所以在 MyViewController 中编写如下代码 - (NSUInteger)支持的接口定向方法

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

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

IOS8或以上版本

对于那些想知道屏幕尺寸(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;
}
}