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?
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:
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;
}
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;
}
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));
}
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.
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 {
}
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.
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
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;
}
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];
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;
}
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
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.
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
}
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.
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).
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;
}
}