web-dev-qa-db-fra.com

Est-ce que [UIScreen mainScreen] .bounds.size est dépendant de l'orientation dans iOS8?

J'ai exécuté le code suivant sous iOS 7 et 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);

Voici le résultat de iOS 8:

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

En comparant le résultat dans iOS 7:

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

Existe-t-il une documentation spécifiant ce changement? Ou s'agit-il d'un bogue temporaire dans les API iOS 8?

183
lwxted

Oui, cela dépend de l'orientation dans iOS8, pas d'un bogue. Vous pouvez consulter la session 214 de WWDC 2014 pour plus d'informations: "Afficher les avancées du contrôleur dans iOS 8"

Citation de la présentation:

UIScreen est maintenant orienté interface:

  • [UIScreen bounds] désormais orienté interface
  • [UIScreen applicationFrame] désormais orienté interface
  • Les notifications de cadre de la barre d'état sont orientées interface
  • Les notifications de cadre de clavier sont orientées interface
173
vhristoskov

Oui, cela dépend de l'orientation dans iOS8.

J'ai écrit une méthode Util pour résoudre ce problème pour les applications devant prendre en charge les anciennes versions du système d'exploitation.

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

Oui, en effet, la taille de l’écran dépend désormais de l’orientation dans iOS 8. Cependant, il est parfois souhaitable d’obtenir une taille fixée à l’orientation portrait. Voici comment je le fais.

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

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

Oui, cela dépend maintenant de l'orientation.

Je préfère la méthode ci-dessous pour obtenir la taille de l’écran d’une manière indépendante de l’orientation à certaines des réponses ci-dessus, à la fois parce que c’est plus simple et parce que cela ne dépend pas du code d’orientation (dont l’état peut dépendre du moment où ils sont appelés) ou lors de la vérification de la version. Vous voudrez peut-être le nouveau comportement iOS 8, mais cela fonctionnera si vous souhaitez qu'il soit stable sur toutes les versions d'iOS.

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

En lien avec cette question, car cela résout mon problème, voici deux définitions que j’utilise pour les calculs de largeur et de hauteur d’écran:

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

Si vous prenez en charge à la fois iOS 7 et iOS 8, il s'agit de la meilleure solution à ce problème.

11
Antoine

Vous pouvez utiliser nativeBounds (indépendant de l'orientation)

nativeBounds

Le rectangle de délimitation de l'écran physique, mesuré en pixels. (lecture seulement)

Déclaration rapide

  var nativeBounds: CGRect { get }

Ce rectangle est basé sur le périphérique dans une orientation portrait. Cette valeur ne change pas lorsque l'appareil est en rotation.

détection de la hauteur de l'appareil:

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

}

détection de la largeur de l'appareil:

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

}
9
Leo Dabus

Ce n'est pas un bug dans iOS 8 SDK. Ils ont fait dépendre l'orientation des interfaces de bornes. Selon votre question sur une référence ou une documentation, je vous recommande fortement de regarder View Controller Advancements in iOS 8 it est 214 session de WWDC 2014 . La partie la plus intéressante (selon vos doutes) est Screen Coordinates qui commence à 50h45.

8
Julian Król

Oui, cela dépend de l'orientation dans iOS8.

Voici comment vous pouvez utiliser une méthode cohérente pour lire les limites de manière iOS 8 dans des versions de SDK et de systèmes d'exploitation.

#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
5
hfossli

Ma solution est une combinaison de MaxK's et hfossli. J'ai fait cette méthode sur une catégorie de UIScreen et il n'a aucune vérification de version (ce qui est une mauvaise pratique):

//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;
}
4
Uzair Khan

La méthode ci-dessous peut être utilisée pour trouver les limites de l'écran pour une orientation donnée, indépendamment de la version iOS. Cette méthode renverra les limites en fonction de la taille d'écran du périphérique et donnera la même valeur CGRect indépendamment de la version iOS.

- (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]; 
3
user4226071

J'avais besoin d'une fonction d'assistance rapide conservant le même comportement que iOS7 sous iOS8 - cela m'a permis d'échanger mes appels [[UIScreen mainScreen] bounds] sans toucher à un autre code ...

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

C'est ce que j'ai utilisé pour calculer le rect correct:

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
1
hhamm

Mon problème était lié à la trame UIWindows qui se passait en moins. Donc fait le code comme ci-dessous dans MyViewController - (NSUInteger) supportedInterfaceOrientations, méthode

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

Et ça marche pour moi l'essayer.

1
Hardik Mamtora

Il suffit d’ajouter la version Swift d’une excellente fonction cbartel mentionnée ci-dessus.

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
}
1
Martin Koles

Une chose que j'ai notée est que le ordre des orientations d'interface prises en charge dans Info.plist est important. J'ai eu le problème de cette question avec mon application (qui fait l'orientation dans le code), mais je n'ai spécifié nulle part que l'orientation par défaut est Portrait.

Je pensais que l'orientation par défaut était Portrait dans tous les cas.

Réorganiser les éléments dans Info.plist, en mettant Portrait en premier, a restauré le comportement attendu.

0
epx

Cela donnera le bon appareil dans iOS7 et iOS8 les deux,

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

// Vous pouvez également ajouter d'autres périphériques (i.e.iPad).

0
Zaid Pathan

iOS 8 ou supérieur

Une solution pour ceux qui souhaitent connaître la taille de l’écran en points (l’écran de 3,5 pouces a 320 × 480 points, l’écran de 4,0 pouces a 320 × 568 points, etc.) serait:

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