在调用 willRotateToInterfaceOrientation 时,iOS 7 与 iOS 8 上的 mainScreen 边界大小不同

Posted

技术标签:

【中文标题】在调用 willRotateToInterfaceOrientation 时,iOS 7 与 iOS 8 上的 mainScreen 边界大小不同【英文标题】:mainScreen bounds size differs on iOS 7 vs iOS 8 upon calling willRotateToInterfaceOrientation 【发布时间】:2014-11-09 00:22:13 【问题描述】:

我知道 ios 8 现在会针对当前界面方向返回正确的屏幕尺寸。要获取 iOS 7 中某个方向的设备宽度,如果方向为横向,则必须返回高度;如果方向为纵向,则必须返回宽度,但您始终可以在 iOS 8 中返回宽度。我已经考虑到了这一点我正在开发的应用程序将支持 iOS 7 和 8。(参见下面的代码)

但是,我注意到另一个不同之处。如果我调用此方法并传入它将是的方向(从willRotateToInterfaceOrientation 获得),在 iOS 7 上它会返回正确的宽度,但在 iOS 8 上它会返回旧(当前)方向的宽度.

当我知道 iOS 8 和 iOS 7 上当前或将要的方向时,如何获取屏幕宽度?

虽然我可以只交换 iOS 8 的宽度和高度,但当设备未转换到新方向时调用此函数时,这将返回不正确的值。我可以创建两种不同的方法,但我正在寻找更清洁的解决方案。

- (CGFloat)screenWidthForOrientation:(UIInterfaceOrientation)orientation

    NSString *reqSysVer = @"8.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending) 
        return [UIScreen mainScreen].bounds.size.width;
    

    CGRect screenBounds = [UIScreen mainScreen].bounds;
    CGFloat width = CGRectGetWidth(screenBounds);
    CGFloat height = CGRectGetHeight(screenBounds);

    if (UIInterfaceOrientationIsPortrait(orientation)) 
        return width;
     else if (UIInterfaceOrientationIsLandscape(orientation)) 
        return height;
    
    return width;

用例:

运行 iOS 7 的 iPad:

viewDidAppear 中调用[self screenWidthForOrientation:[UIApplication sharedApplication].statusBarOrientation] 会返回正确的宽度 在willRotateToInterfaceOrientation:toInterfaceOrientation:duration 中调用[self screenWidthForOrientation:toInterfaceOrientation] 会返回正确的宽度

运行 iOS 8 的 iPad:

viewDidAppear 中调用[self screenWidthForOrientation:[UIApplication sharedApplication].statusBarOrientation] 会返回正确的宽度 在willRotateToInterfaceOrientation:toInterfaceOrientation:duration 中调用[self screenWidthForOrientation:toInterfaceOrientation] 会返回不正确的宽度(旋转发生前的当前值)

【问题讨论】:

【参考方案1】:

这是我在应用约束之前为 iOS7 / iOS8 计算正确宽度和高度的代码。

- (void) applyConstraints:(UIInterfaceOrientation)toInterfaceOrientation
   
    CGSize screenSize = [[UIScreen mainScreen] bounds].size;
    CGFloat heightOfScreen;
    CGFloat widthOfScreen;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) 
        // iOS 8.0 and later code here
        if ([UIApplication sharedApplication].statusBarOrientation == toInterfaceOrientation) 
            heightOfScreen = screenSize.height;
            widthOfScreen = screenSize.width;
         else 
            heightOfScreen = screenSize.width;
            widthOfScreen = screenSize.height;
        
     else 
        if (UIDeviceOrientationIsLandscape(toInterfaceOrientation)) 
            heightOfScreen = screenSize.width;
            widthOfScreen = screenSize.height;
         else 
            heightOfScreen = screenSize.height;
            widthOfScreen = screenSize.width;
        
    
    //Applying new constraints
    ...

它不是那么漂亮,但它有效 =)

【讨论】:

【参考方案2】:

在 iOS 8 中,旋转和坐标系的整个性质完全改变了。你不应该使用像willRotate这样的事件;它们已被弃用。整个应用程序旋转,包括屏幕。不再有旋转变换;整个应用程序(屏幕、窗口、根视图)变得越来越宽,这就是您知道发生了什么事情的方式(或者您可以注册以了解状态栏改变其方向)。如果您想知道 设备 坐标,与旋转无关,这就是新的屏幕坐标空间的用途(fixedCoordinateSpace 是不旋转的)。

【讨论】:

以上是关于在调用 willRotateToInterfaceOrientation 时,iOS 7 与 iOS 8 上的 mainScreen 边界大小不同的主要内容,如果未能解决你的问题,请参考以下文章

在webservice的一次调用中能循环调用接口方法

返回函数调用与仅在递归期间再次调用函数有啥区别?

在 foreach 中调用类仅最后一次调用有效

在 JSX 中调用 javascript 函数:为啥在没有 () 的情况下调用函数?

c语言中,在一个自定义函数里面只能调用一个自定义函数吗?可以调用多个吗?如果可以怎么调用?

为啥 C# 编译器会在最后一个方法调用是条件调用时删除一串方法调用?