Aplicaciones iOS 6: ¿cómo lidiar con el tamaño de pantalla del iPhone 5?

Posible duplicado:
¿Cómo desarrollar o migrar aplicaciones para la resolución de pantalla del iPhone 5?

Me preguntaba cómo deberíamos lidiar con el tamaño de pantalla más grande del iPhone 5.

Como tiene más píxeles de altura, elementos como GCRectMake que usan coordenadas (y duplican los píxeles con el problema retina / no retina) no funcionarán a la perfección entre las versiones, como sucedió cuando obtuvimos la Retina .

¿Y tendremos que diseñar dos storyboards, al igual que para el iPad?

Personalmente, no creo que Apple le pida que verifique el tamaño de la pantalla cada vez que tenga que dibujar algo, como dicen muchas respuestas. ¿Eso pasa con el iPad?

Todas las aplicaciones continuarán funcionando en la pantalla verticalmente estirada de lo que podría decir en la presentación de hoy. Serán letterbox o básicamente los 88 puntos adicionales en altura serían simplemente negros.

Si solo planea soportar iOS 6+, entonces definitivamente considere usar Auto Layout. Elimina todo el manejo de disposición fija y en su lugar utiliza restricciones para establecer cosas. Nada será codificado, y tu vida será mucho más simple.

Sin embargo, si tiene que admitir iOS más antiguos, realmente depende de su aplicación. La mayoría de las aplicaciones que usan una barra de navegación estándar y / o una barra de tabs, simplemente pueden expandir el contenido en el medio para agotar esos puntos adicionales. Configure la máscara de aumento de tamaño del contenido central para expandirla en ambas direcciones.

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

Funciona muy bien para las vistas de tabla, sin embargo, si su aplicación utiliza un diseño perfecto para mostrar el contenido, entonces la mejor opción sería volver a imaginar el contenido para que pueda acomodar alturas diferentes.

Si eso no es posible, entonces la única opción restante es tener dos IU (antes del iPhone 5 y iPhone 5).

Si eso suena feo, entonces podrías ir con el modelo de buzón predeterminado donde los puntos / píxeles adicionales solo aparecen en negro.

Editar

Para permitir que sus aplicaciones funcionen con iPhone 5, debe agregar una versión retina de la imagen del iniciador. Debe llamarse Default-568h@2x.png . Y tiene que ser de calidad retina, no hay compatibilidad con versiones anteriores aquí 🙂

También puede seleccionar esta imagen desde dentro de Xcode. Vaya al objective y, en la sección Resumen, busque Lanzar imágenes. La imagen tiene que tener un tamaño de 640×1136 píxeles. Aquí hay una captura de pantalla de dónde encontrarlo, si eso ayuda.

Captura de pantalla de Xcode

Necesita agregar una imagen PNG de 640×1136 píxeles ( Default-568h@2x.png ) como una imagen predeterminada de 4 pulgadas de su proyecto, y usará espacios adicionales (sin esfuerzos en aplicaciones simples basadas en tablas, los juegos requerirán más esfuerzos) .

Creé una pequeña categoría de UIDevice para tratar con todas las resoluciones de pantalla. Puede obtenerlo aquí , pero el código es el siguiente:

Archivo UIDevice + Resolutions.h :

 enum { UIDeviceResolution_Unknown = 0, UIDeviceResolution_iPhoneStandard = 1, // iPhone 1,3,3GS Standard Display (320x480px) UIDeviceResolution_iPhoneRetina4 = 2, // iPhone 4,4S Retina Display 3.5" (640x960px) UIDeviceResolution_iPhoneRetina5 = 3, // iPhone 5 Retina Display 4" (640x1136px) UIDeviceResolution_iPadStandard = 4, // iPad 1,2,mini Standard Display (1024x768px) UIDeviceResolution_iPadRetina = 5 // iPad 3 Retina Display (2048x1536px) }; typedef NSUInteger UIDeviceResolution; @interface UIDevice (Resolutions) - (UIDeviceResolution)resolution; NSString *NSStringFromResolution(UIDeviceResolution resolution); @end 

Archivo UIDevice + Resolutions.m :

 #import "UIDevice+Resolutions.h" @implementation UIDevice (Resolutions) - (UIDeviceResolution)resolution { UIDeviceResolution resolution = UIDeviceResolution_Unknown; UIScreen *mainScreen = [UIScreen mainScreen]; CGFloat scale = ([mainScreen respondsToSelector:@selector(scale)] ? mainScreen.scale : 1.0f); CGFloat pixelHeight = (CGRectGetHeight(mainScreen.bounds) * scale); if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){ if (scale == 2.0f) { if (pixelHeight == 960.0f) resolution = UIDeviceResolution_iPhoneRetina4; else if (pixelHeight == 1136.0f) resolution = UIDeviceResolution_iPhoneRetina5; } else if (scale == 1.0f && pixelHeight == 480.0f) resolution = UIDeviceResolution_iPhoneStandard; } else { if (scale == 2.0f && pixelHeight == 2048.0f) { resolution = UIDeviceResolution_iPadRetina; } else if (scale == 1.0f && pixelHeight == 1024.0f) { resolution = UIDeviceResolution_iPadStandard; } } return resolution; } @end 

Así es como debes usar este código.

1) Agregue los archivos anteriores UIDevice + Resolutions.h & UIDevice + Resolutions.m a su proyecto

2) Agregue la línea #import “UIDevice + Resolutions.h” a su ViewController.m

3) Agregue este código para verificar qué versiones de dispositivo está tratando con

 int valueDevice = [[UIDevice currentDevice] resolution]; NSLog(@"valueDevice: %d ...", valueDevice); if (valueDevice == 0) { //unknow device - you got me! } else if (valueDevice == 1) { //standard iphone 3GS and lower } else if (valueDevice == 2) { //iphone 4 & 4S } else if (valueDevice == 3) { //iphone 5 } else if (valueDevice == 4) { //ipad 2 } else if (valueDevice == 5) { //ipad 3 - retina display } 

Acabo de actualizar y enviar una versión iOS 6.0 de una de mis aplicaciones a la tienda. Esta versión es retrocompatible con iOS 5.0, así que guardé el método shouldAutorotateToInterfaceOrientation: y agregué los nuevos como se shouldAutorotateToInterfaceOrientation: continuación.

Tenía que hacer lo siguiente:

La autorotación está cambiando en iOS 6. En iOS 6, el método shouldAutorotateToInterfaceOrientation: de UIViewController está en desuso. En su lugar, debe usar la shouldAutorotate supportedInterfaceOrientationsForWindow: para la shouldAutorotate supportedInterfaceOrientationsForWindow: y shouldAutorotate métodos. Por lo tanto, agregué estos nuevos métodos (y mantuve el viejo para la compatibilidad con iOS 5):

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAllButUpsideDown; } 
  • Usó el método viewWillLayoutSubviews del controlador de vista y viewWillLayoutSubviews el diseño utilizando el rectángulo de límites de la vista.
  • Controladores de vista modal: The willRotateToInterfaceOrientation:duration:
    willAnimateRotationToInterfaceOrientation:duration: y
    didRotateFromInterfaceOrientation: métodos ya no se didRotateFromInterfaceOrientation: en ningún controlador de vista que realice una presentación en pantalla completa
    en sí mismo , por ejemplo, presentViewController:animated:completion:
  • Luego arreglé el diseño automático para las vistas que lo necesitaban.
  • Copió imágenes del simulador para la vista de inicio y vistas para la tienda de iTunes en PhotoShop y las exportó como archivos png.
  • El nombre de la imagen predeterminada es: Default-568h@2x.png y el tamaño es 640 × 1136. También está permitido suministrar 640 × 1096 para el mismo modo de retrato (barra de estado eliminada). También se pueden suministrar tamaños similares en modo horizontal si su aplicación solo permite la orientación horizontal en el iPhone.
  • He descartado la compatibilidad con versiones anteriores de iOS 4. La razón principal es que se ha eliminado el soporte para el código de armv6 . Por lo tanto, todos los dispositivos que puedo admitir ahora (ejecutando armv7 ) se pueden actualizar a iOS 5.
  • También soy código de generación de armv7s para admitir el iPhone 5 y, por lo tanto, no puedo usar marcos de terceros (como Admob, etc.) hasta que se actualicen.

Eso fue todo pero recuerde probar la autorrotación en iOS 5 e iOS 6 debido a los cambios en la rotación.

No.

 if ([[UIScreen mainScreen] bounds].size.height > 960) 

en el iPhone 5 está mal

 if ([[UIScreen mainScreen] bounds].size.height == 568) 
 @interface UIDevice (Screen) typedef enum { iPhone = 1 << 1, iPhoneRetina = 1 << 2, iPhone5 = 1 << 3, iPad = 1 << 4, iPadRetina = 1 << 5 } DeviceType; + (DeviceType)deviceType; @end 

.metro

 #import "UIDevice+Screen.h" @implementation UIDevice (Screen) + (DeviceType)deviceType { DeviceType thisDevice = 0; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { thisDevice |= iPhone; if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)]) { thisDevice |= iPhoneRetina; if ([[UIScreen mainScreen] bounds].size.height == 568) thisDevice |= iPhone5; } } else { thisDevice |= iPad; if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)]) thisDevice |= iPadRetina; } return thisDevice; } @end 

De esta manera, si desea detectar si se trata de un iPhone o iPad (independientemente del tamaño de la pantalla), solo debe usar:

 if ([UIDevice deviceType] & iPhone) 

o

 if ([UIDevice deviceType] & iPad) 

Si quieres detectar solo el iPhone 5, puedes usar

 if ([UIDevice deviceType] & iPhone5) 

A diferencia de Malcoms, responde donde necesitarías verificar solo para descubrir si se trata de un iPhone,

 if ([UIDevice currentResolution] == UIDevice_iPhoneHiRes || [UIDevice currentResolution] == UIDevice_iPhoneStandardRes || [UIDevice currentResolution] == UIDevice_iPhoneTallerHiRes)` 

De ninguna manera tiene una gran ventaja sobre el otro, es solo una preferencia personal.

El comentario de @ Pascal sobre la pregunta del OP es correcto. Simplemente agregando la imagen, elimina los bordes negros y la aplicación usará la altura completa.

Deberá realizar ajustes en cualquier CGRects determinando que el dispositivo está usando la pantalla más grande. Es decir, si necesita algo alineado con la parte inferior de la pantalla.

Estoy seguro de que hay un método integrado, pero no he visto nada y todavía hay mucho bajo NDA, por lo que el método que utilizamos en nuestras aplicaciones es simplemente una función global. Agregue lo siguiente a su archivo .pch y luego realice una llamada simple if( is4InchRetina() ) { ... } para realizar ajustes en sus CGRects, etc.

 static BOOL is4InchRetina() { if (![UIApplication sharedApplication].statusBarHidden && (int)[[UIScreen mainScreen] applicationFrame].size.height == 548 || [UIApplication sharedApplication].statusBarHidden && (int)[[UIScreen mainScreen] applicationFrame].size.height == 568) return YES; return NO; } 

Creo que puedes usar [UIScreen mainScreen].bounds.size.height y calcular el paso para tus objetos. Cuando calcule el paso, puede establecer coordenadas para dos resoluciones.

O puede obtener la altura como arriba y if(iphone5) then... else if(iphone4) then... else if(ipad) . Algo como esto.

Si usa storyboards, entonces creo que debe crear uno nuevo para el nuevo iPhone, creo.

Como tiene más píxeles de altura, cosas como GCRectMake que usan coordenadas no funcionarán a la perfección entre versiones, como sucedió cuando obtuvimos la Retina.

Bueno, funcionan de la misma manera con las pantallas Retina. Es solo que 1 unidad en el sistema de coordenadas de CoreGraphics corresponderá a 2 píxeles físicos, pero no tienes / no tienes que hacer nada, la lógica se mantuvo igual. (¿Alguna vez has intentado ejecutar una de tus aplicaciones que no son retina en un iPhone con retina ? )

Para la pregunta real: es por eso que no debería usar CGRectMakes explícitos y co … Es por eso que tiene cosas como [[UIScreen mainScreen] applicationFrame] .