Detección de tamaños de pantalla de iPhone 6/6 + en valores de puntos

Dado los nuevos tamaños de pantalla del iPhone 6 anunciados:

iPhone 6: 1334h * 750w @2x (in points: 667h * 375w) iPhone 6+: 1920 * 1080 @3x (in points: 640h * 360w) 

Me preguntaba si hay un código que me permita detectar qué tamaño de pantalla es el dispositivo del usuario, para poder ajustar y clasificar los UIImages y otros materiales de acuerdo con el dispositivo del usuario.

Hasta ahora, he estado usando lo siguiente:

 - (NSString *) platform{ size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *machine = malloc(size); sysctlbyname("hw.machine", machine, &size, NULL, 0); NSString *platform = [NSString stringWithUTF8String:machine]; free(machine); return platform; } - (NSString *) platformString{ NSString *platform = [self platform]; if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 1G"; if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; if ([platform isEqualToString:@"iPhone3,3"]) return @"Verizon iPhone 4"; if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5 (GSM)"; if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5 (GSM+CDMA)"; if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c (GSM)"; if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c (GSM+CDMA)"; if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s (GSM)"; if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s (GSM+CDMA)"; if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G"; if ([platform isEqualToString:@"iPad1,1"]) return @"iPad"; if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)"; if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)"; if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)"; if ([platform isEqualToString:@"iPad2,4"]) return @"iPad 2 (WiFi)"; if ([platform isEqualToString:@"iPad2,5"]) return @"iPad Mini (WiFi)"; if ([platform isEqualToString:@"iPad2,6"]) return @"iPad Mini (GSM)"; if ([platform isEqualToString:@"iPad2,7"]) return @"iPad Mini (GSM+CDMA)"; if ([platform isEqualToString:@"iPad3,1"]) return @"iPad 3 (WiFi)"; if ([platform isEqualToString:@"iPad3,2"]) return @"iPad 3 (GSM+CDMA)"; if ([platform isEqualToString:@"iPad3,3"]) return @"iPad 3 (GSM)"; if ([platform isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)"; if ([platform isEqualToString:@"iPad3,5"]) return @"iPad 4 (GSM)"; if ([platform isEqualToString:@"iPad3,6"]) return @"iPad 4 (GSM+CDMA)"; if ([platform isEqualToString:@"iPad4,1"]) return @"iPad Air (WiFi)"; if ([platform isEqualToString:@"iPad4,2"]) return @"iPad Air (Cellular)"; if ([platform isEqualToString:@"iPad4,4"]) return @"iPad mini 2G (WiFi)"; if ([platform isEqualToString:@"iPad4,5"]) return @"iPad mini 2G (Cellular)"; if ([platform isEqualToString:@"i386"]) return @"Simulator"; if ([platform isEqualToString:@"x86_64"]) return @"Simulator"; return platform; } 

Como tal, ¿debería asumir que el iPhone7,1 y el iPhone7,2 son el iPhone 6, mientras que el iPhone7,3 y el iPhone7.4 son las ventajas? Si alguien tiene una forma más concreta de decir que sería genial, gracias.

La primera pantalla será la pantalla del dispositivo. Tenga en count que antes deben agregarse imágenes de inicio para los nuevos teléfonos; de lo contrario, la aplicación se está ejecutando en Modo Zoom para aplicaciones anteriores: aquí está el código que usé para verificar esto. Nota: Esto solo funciona con la versión iOS 8 y posterior :

 UIScreen *mainScreen = [UIScreen mainScreen]; NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f", NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale); 

Código para detectar iPhone 6 Plus:

 #define IS_PAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) #define IS_PHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) -(BOOL)iPhone6PlusDevice{ if (!IS_PHONE) return NO; if ([UIScreen mainScreen].scale > 2.9) return YES; // Scale is only 3 when not in scaled mode for iPhone 6 Plus return NO; } 

o

 -(BOOL) iPhone6PlusUnZoomed{ if ([self iPhone6PlusDevice]){ if ([UIScreen mainScreen].bounds.size.height > 720.0) return YES; // Height is 736, but 667 when zoomed. } return NO; } 

Nota: Si está buscando iPhone 6 Plus, para ajustar la interfaz de usuario, no confíe en .nativeScale , ya que el simulador y el dispositivo real dan resultados diferentes. Debido al comentario a continuación. La escala es una CGFloat y, por lo tanto, el código no debe verificar la igualdad, ya que algunos valores de flotación nunca serán iguales.


Después de agregar imágenes de inicio para el nuevo iPhone6 y 6 Plus , los tamaños cambian. Escala las aplicaciones más antiguas para adaptarse a la pantalla.

Tamaño para iPhone 6 Plus y iPhone 6S Plus con escala de 3x (nombre Apple: Retina HD 5.5 ), espacio de coorderadas: 414 x 736 puntos y 1242 x 2208 píxeles, 401 ppi, el tamaño físico de la pantalla es de 2,7 x 4,8 pulgadas o 68 x 122 mm :

 Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000 

Tamaño para iPhone 6 y iPhone 6S con escala de 2x (nombre Apple: Retina HD 4.7 ), espacio de coorderadas: 375 x 667 puntos y 750 x 1334 píxeles, 326 ppi, el tamaño físico de la pantalla es de 2,3 x 4,1 pulgadas o 58 x 104 mm :

 Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000 

Y el iPhone 5 para la comparación es 640 x 1136, iPhone 4 640 x 960.

Nota: Cargue LaunchImages, de lo contrario, la aplicación se ejecutará a escala y no mostrará la escala correcta ni los tamaños de pantalla.

Comparando iPhone 6 y 6 Plus

Si prefiere las macros aquí son las que puede usar para diferenciar entre los models de iPhone. Estos se basan en los valores de puntos.

 #define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)480) < DBL_EPSILON) #define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON) #define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON) #define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON) 

Utilizo el siguiente código para determinar qué dispositivo se está ejecutando (es un poco rápido y sucio, pero hace el truco)

 if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){ CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; if( screenHeight < screenWidth ){ screenHeight = screenWidth; } if( screenHeight > 480 && screenHeight < 667 ){ NSLog(@"iPhone 5/5s"); } else if ( screenHeight > 480 && screenHeight < 736 ){ NSLog(@"iPhone 6"); } else if ( screenHeight > 480 ){ NSLog(@"iPhone 6 Plus"); } else { NSLog(@"iPhone 4/4s"); } } 

(Esto solo funciona cuando el iPhone 6/6 Plus está habilitado agregando las pantallas de bienvenida apropiadas)

En el dispositivo físico, los límites de la pantalla principal del iPhone 6 Plus son 2208×1242 y NativeBounds es 1920×1080. Hay una escala de hardware involucrada para cambiar el tamaño a la pantalla física.

En el simulador, los límites de la pantalla principal del iPhone 6 Plus y NativeBounds son ambos 2208×1242.

En otras palabras … Los videos, OpenGL y otras cosas basadas en CALayers que tratan con píxeles tratarán con el framebuffer de 1920×1080 real en el dispositivo (o 2208×1242 en el sim). Las cosas que tratan con puntos en UIKit se tratarán con los límites de 2208×1242 (x3) y se escalarán según corresponda en el dispositivo.

El simulador no tiene acceso al mismo hardware que está haciendo escala en el dispositivo y no hay mucho beneficio en simularlo en el software, ya que producirían resultados diferentes al hardware. Por lo tanto, tiene sentido establecer los nativeBounds de la pantalla principal de un dispositivo simulado en los límites de la pantalla principal del dispositivo físico.

iOS 8 agregó API a UIScreen (nativeScale y nativeBounds) para permitir que un desarrollador determine la resolución de CADisplay correspondiente a UIScreen.

Revisa la list actualizada en wiki , ahí obtuve 7,2 para iPhone 6 y 7,1 para iPhone 6 plus.

Puede detectar iPhone 6 Plus en function de su escala nativa, utilizando esta macro:

 #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) #define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f) 

La respuesta de Hannes Sverrisson es casi correcta. El sistema de coorderadas iPhone 6 es, de hecho, más grande que los 5s. Usando su código:

 UIScreen *mainScreen = [UIScreen mainScreen]; NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f", NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale); 

El sistema de coorderadas para las aplicaciones que proporcionan las imágenes de lanzamiento correctas son:

Tamaño para iPhone 6 (Retina HD 4.7) con escala de 2x, espacio de coorderadas: 375 x 667 y 750 x 1334 puntos reales:

 Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000 

Tamaño para iPhone 6 Plus (Retina HD 5.5) con escala de 3x, espacio de coorderadas: 414 x 736 y 1242 x 2208 puntos reales:

 Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000 

Esto es lo que uso en mi aplicación con iOS 8:

 window=[[[UIApplication shanetworkingApplication] windows] firstObject]; NSLog(@"screenHeight=%f width=%f",window.frame.size.height,window.frame.size.width); if (window.frame.size.height == 480) { do stuff here... } 

Antes de Xcode6 / iOS 8, usé esto, pero los límites de pantalla no funcionan correctamente con el simulador de tamaño variable o al less no en las betas de Xcode6 …

 CGRect screenBounds=[[UIScreen mainScreen] bounds]; if (screenBounds.size.height >= 568) { do stuff here... } 

Tuve que detectar el iPhone 6 Plus en una aplicación creada con iOS 7. Como la escala nativa no está disponible en [UIScreen mainScreen] intenté usar la escala [UIScreen mainScreen]], pero esto acaba de regresar 2.0. Entonces encontré esta solución para detectar el iPhone 6 Plus en iOS 7 (también debería funcionar en iOS 8):

 -(BOOL)iPhone6Plus{ BOOL isiPhone6Plus = NO; SEL selector = NSSelectorFromString(@"scale"); if ([[UIScreen mainScreen] respondsToSelector:selector]) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIScreen mainScreen]]; [invocation invoke]; float returnValue; [invocation getReturnValue:&returnValue]; if (returnValue == 3.0) { isiPhone6Plus = YES; } NSLog(@"ScaleFactor %1.2f", returnValue); } return isiPhone6Plus; 

}

La parte interesante de este código es que, si utilizo NSInvocation, el valor de retorno del selector de escala será 3.0. Llamar a este método directamente en iOS 7 devuelve 2.0.

Los tres dispositivos tienen (casi) el mismo número de puntos por pulgada. Entonces tus imágenes tendrán automáticamente el mismo tamaño físico.

Use [[UIScreen mainScreen] bounds] para get el número total de puntos en la pantalla. Divida por 163 para get el tamaño aproximado en pulgadas si realmente lo desea.

Tenga en count que el 6+ no devuelve 1080p porque no se reproduce en un búfer de 1080p. Hace que la producción sea de aproximadamente 160 puntos por pulgada, usando activos de 3x.

No hay necesidad de adivinar por segunda vez.

Por ejemplo, si escribe este código:

 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 163, 163)]; view.backgroundColor = [UIColor networkingColor]; [self.view addSubview:view]; 

Obtendrá una vista que es más o less el mismo tamaño físico, una pulgada cuadrada, en todos los dispositivos iOS.

Apple ya ha hecho el trabajo duro, así que no tienes que hacerlo.

a mí esto me funciona

 if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){ UIStoryboard *storyBoard; CGSize result = [[UIScreen mainScreen] bounds].size; CGFloat scale = [UIScreen mainScreen].scale; result = CGSizeMake(result.width * scale, result.height * scale); if(result.height == 1136){ storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_5" bundle:nil]; UIViewController *initViewController = [storyBoard instantiateInitialViewController]; [self.window setRootViewController:initViewController]; } else if(result.height == 1334){ storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6" bundle:nil]; UIViewController *initViewController = [storyBoard instantiateInitialViewController]; [self.window setRootViewController:initViewController]; } else if(result.height == 2208){ storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6_plus" bundle:nil]; UIViewController *initViewController = [storyBoard instantiateInitialViewController]; [self.window setRootViewController:initViewController]; } else if(result.height == 960){ storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_4" bundle:nil]; UIViewController *initViewController = [storyBoard instantiateInitialViewController]; [self.window setRootViewController:initViewController]; } } else { UIStoryboard *storyBoard; storyBoard = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil]; UIViewController *initViewController = [storyBoard instantiateInitialViewController]; [self.window setRootViewController:initViewController]; } 

esto está garantizado para comstackr en xcode 5 (xocde 6 en este momento sigue siendo escamosa, y no puede enviar un ipa a iTunes para conectarse para la aprobación de la tienda de aplicaciones con el software beta, que xcode 6 es ahora)

la cosa es que xcode 5 no reconocerá el selector de nativeScale … así es como puedes hacerlo en time de ejecución:

 + (BOOL)isIphone6Plus { SEL selector = NSSelectorFromString(@"nativeScale"); if ([[UIScreen mainScreen] respondsToSelector:selector]) { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIScreen mainScreen]]; [invocation invoke]; float returnValue; [invocation getReturnValue:&returnValue]; NSLog(@"::: this is native scale %f", returnValue); return (returnValue == 3.0f); } else { // iphone 6 plus come prepackaged with iOS8.. // so if the phone doesn't know what nativeScale means // it's not an iphone6plus phone return NO; } } 

Una cosa interesante para recordar al leer los tamaños de pantalla en mi iPhone 6 Plus fue que cuando lo configuró en el modo "Zoomed" aparecerá como una altura de iPhone 6 (667) y cuando lo haya configurado en "Estándar" Aparecerá como (736). No debería importar realmente, pero si específicamente quisieras saber el tipo de dispositivo por alguna razón (Tal vez Reportaje), esto podría engañarte.

Mira esto

Aquí está el código fuente actualizado que está utilizando.

Se agregaron models iPhone 6 y iPhone 6 Plus.

Una cosa importante que las respuestas anteriores están [[UIScreen mainScreen] bounds] es el hecho de que en iOS7 y debajo, cuando se comtesting [[UIScreen mainScreen] bounds] para los límites de pantalla, siempre se muestra el ancho y la altura como el mismo sin importar la orientación del teléfono está en. Por lo tanto, si se trata de un iPhone5 en modo horizontal, seguirá enumerando el ancho como 320 y alto como 568. En iOS8, esto cambió, ahora si ese mismo iPhone5 está en paisaje, mostrará el ancho como 568 y la altura como 320. A continuación hay methods que explican esto:

 + (BOOL) deviceHasFourInchScreen { return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:568.0]; } + (BOOL) deviceHasFourPointSevenInchScreen { return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:667.0]; } + (BOOL) deviceHasFivePointFiveInchScreen { return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:3.0 height:736.0]; } + (BOOL) deviceHasScreenWithIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom scale:(CGFloat)scale height:(CGFloat)height { CGRect mainScreenBounds = [[UIScreen mainScreen] bounds]; CGFloat mainScreenHeight; if ([OperatingSystemVersion operatingSystemVersionLessThan:@"8.0"]) { mainScreenHeight = mainScreenBounds.size.height; } else { mainScreenHeight = (UIDeviceOrientationIsLandscape([[UIApplication shanetworkingApplication] statusBarOrientation])) ? mainScreenBounds.size.width : mainScreenBounds.size.height; } if ([[UIDevice currentDevice] userInterfaceIdiom] == userInterfaceIdiom && [[UIScreen mainScreen] scale] == scale && mainScreenHeight == height) { return YES; } else { return NO; } } 

También aquí están los methods de class de OperatingSystem que lo acompañan:

 + (NSString *) currentOperatingSystemVersion { return [[UIDevice currentDevice] systemVersion]; } + (BOOL) operatingSystemVersionLessThanOrEqualTo:(NSString *) operatingSystemVersionToCompare { return ([[self currentOperatingSystemVersion] compare: operatingSystemVersionToCompare options:NSNumericSearch] != NSOrdenetworkingDescending); }