Search code examples
iosobjective-cios7rotationios8

mainScreen bounds size differs on iOS 7 vs iOS 8 upon calling willRotateToInterfaceOrientation


I know iOS 8 now returns the proper screen dimensions for the current interface orientation. To get the device width for an orientation in iOS 7 you had to return the height if the orientation is landscape or width if the orientation is portrait, but you can always return the width in iOS 8. I have already taken that into consideration for an app I'm developing that will support iOS 7 and 8. (See code below)

However, I noticed another difference. If I call this method and pass in the orientation that it will be (obtained from willRotateToInterfaceOrientation), on iOS 7 it does return the proper width that it will be but on iOS 8 it returns the width for the old (current) orientation.

How can I get the width of the screen when I know the orientation it currently is or will be on iOS 8 and iOS 7?

While I could just swap the width and height for iOS 8, this would return an incorrect value when this function is called while the device isn't transitioning to a new orientation. I could create two different methods but I'm looking for a cleaner solution.

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

Use cases:

iPad running iOS 7:

  • calling [self screenWidthForOrientation:[UIApplication sharedApplication].statusBarOrientation] in viewDidAppear returns the correct width
  • calling [self screenWidthForOrientation:toInterfaceOrientation] in willRotateToInterfaceOrientation:toInterfaceOrientation:duration returns the correct width

iPad running iOS 8:

  • calling [self screenWidthForOrientation:[UIApplication sharedApplication].statusBarOrientation] in viewDidAppear returns the correct width
  • calling [self screenWidthForOrientation:toInterfaceOrientation] in willRotateToInterfaceOrientation:toInterfaceOrientation:duration returns the incorrect width (what it currently is before the rotation occurs)

Solution

  • Here is my code to calculate correct width and height for iOS7 / iOS8 before applying constraints.

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

    It is not so beautiful but it works =)