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

Teniendo en cuenta los nuevos tamaños de pantalla del iPhone 6:

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 tiene el dispositivo del usuario, para poder ajustar y UIImages tamaño de 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 suponer que iPhone7,1 y iPhone7,2 son el iPhone 6, mientras que iPhone7,3 y 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 cuenta que las imágenes de inicio para los teléfonos nuevos deben agregarse antes; de lo contrario, la aplicación se ejecuta en modo Zoom para aplicaciones antiguas: este es el código que utilicé para verificarlo. Nota: Esto solo funciona con la versión iOS 8 y superior :

 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 el iPhone 6 Plus, para ajustar la interfaz de usuario, no confíe en .nativeScale , ya que el simulador y el dispositivo real dan diferentes resultados. Debido al comentario a continuación. Scale es un CGFloat y, por lo tanto, el código no debería verificar la igualdad, ya que algunos valores de los flotantes nunca pueden ser iguales.


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

Tamaño para iPhone 6 Plus y iPhone 6S Plus con escalado @ 3x (nombre de Apple: Retina HD 5.5 ), espacio de coordenadas: 414 x 736 puntos y 1242 x 2208 píxeles, 401 ppp, tamaño físico de pantalla es 2.7 x 4.8 o 68 x 122 mm :

 Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: >, scale: 3.000000, nativeScale: 3.000000 

Tamaño para iPhone 6 y iPhone 6S con escalado @ 2x (nombre de Apple: Retina HD 4.7 ), espacio de coordenadas: 375 x 667 puntos y 750 x 1334 píxeles, 326 ppp, el tamaño físico de la pantalla es de 2.3 x 4.1 in o 58 x 104 mm :

 Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: >, 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á las escalas correctas o 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 modelos 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) 

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

 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 iPhone 6/6 Plus se habilita agregando las pantallas de bienvenida apropiadas)

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

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

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

El simulador no tiene acceso al mismo hardware que está escalando en el dispositivo y no hay mucho beneficio para simularlo en el software ya que produciría resultados diferentes al hardware. Por lo tanto, tiene sentido establecer los elementos nativos 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.

Verifique la lista actualizada en wiki , allí obtuve 7,2 para iPhone 6 y 7,1 para iPhone 6 plus.

Puede detectar iPhone 6 Plus según su escala nativa, usando 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 coordenadas del iPhone 6 es de hecho más grande que el 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 coordenadas para las aplicaciones que proporcionan las imágenes de inicio correctas son:

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

 Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: >, scale: 2.000000, nativeScale: 2.000000 

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

 Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: >, scale: 3.000000, nativeScale: 3.000000 

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

 window=[[[UIApplication sharedApplication] 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, utilicé esto, pero los límites de pantalla no funcionan correctamente con el simulador de tamaño variable o al menos no lo hizo en las betas 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. Debido a que nativeScale no está disponible en [UIScreen mainScreen] traté de usar [UIScreen mainScreen] scale] pero esto acaba de devolver 2.0. Así que se me ocurrió 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 uso 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) la misma cantidad de puntos por pulgada. Entonces tus imágenes tendrán automáticamente el mismo tamaño físico.

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

Tenga en cuenta que el 6+ no devuelve 1080p porque no se procesa en un buffer 1080p. Da como resultado que la salida sea de aproximadamente 160 puntos por pulgada, utilizando activos @ 3x.

No es necesario adivinarlo en segundo lugar.

Por ejemplo, si escribe este código:

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

Obtendrá una vista que tiene prácticamente el mismo tamaño físico, una pulgada cuadrada, en todos los dispositivos iOS.

Apple ya ha hecho el trabajo duro, por lo que no es necesario.

para mí esto funciona para mí

 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 comstackrse en xcode 5 (xocde 6 en este punto todavía es escamoso, y no puede enviar un ipa a itunes connect para la aprobación de la tienda de aplicaciones utilizando el software beta, que es xcode 6 en este momento)

el problema es que xcode 5 no reconocerá el selector nativeScale … así es como puedes hacerlo en tiempo 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 de recordar al leer los tamaños de pantalla en mi iPhone 6 Plus fue que cuando lo tienes configurado en modo “Zoomed” aparecerá como una altura de iPhone 6 (667) y cuando lo tienes configurado en “Standard” aparecerá como (736). Realmente no debería importar, pero si específicamente deseabas saber el tipo de dispositivo por algún motivo (tal vez informar), esto podría engañarte.

Mira esto

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

Se han agregado los modelos 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 abajo, cuando se [[UIScreen mainScreen] bounds] para los límites de la pantalla, siempre se enumera el ancho y la altura como el mismo sin importar la orientación del teléfono está en. Entonces, si se trata de un iPhone5 en modo horizontal, todavía mostrará el ancho como 320 y la altura como 568. En iOS8, esto cambió, ahora si ese mismo iPhone5 está en el paisaje, mostrará el ancho como 568 y la altura como 320. A continuación hay métodos 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 sharedApplication] 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 métodos de la clase OperatingSystem que lo acompañan:

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

Swift 4

 if(kSize.width == 320){ //iphone se }else if(kSize.width == 375 && kSize.height == 667){ //iphone 7 / 8 }else if(kSize.width == 375){ //iphone x }else if(kSize.width == 414){ //iphone 7 plus/ 8 plus } 

kSize es pantalla CGSize

deje kSize = UIScreen.main.bounds.size