¿Cómo detectar el iPhone 5 (dispositivos de pantalla ancha)?

Resuelto Finn Gaida asked hace 54 años • 24 respuestas

Acabo de actualizar a Xcode 4.5 GM y descubrí que ahora puedes aplicar el tamaño '4" Retina' a tu controlador de vista en el guión gráfico.

Ahora, si quiero crear una aplicación que se ejecute en iPhone 4 y 5, por supuesto tengo que crear cada ventana dos veces, pero también tengo que detectar si el usuario tiene un iPhone con pantalla de 3,5" o 4" y luego aplicar la vista.

¿Cómo debería hacer eso?

Finn Gaida avatar Jan 01 '70 08:01 Finn Gaida
Aceptado

En primer lugar, no debe reconstruir todas sus vistas para que se ajusten a una nueva pantalla, ni utilizar diferentes vistas para diferentes tamaños de pantalla.

Utilice las capacidades de cambio de tamaño automático de iOS para que sus vistas puedan ajustarse y adaptarse a cualquier tamaño de pantalla.

Eso no es muy difícil, lea alguna documentación al respecto. Esto le ahorrará mucho tiempo.

iOS 6 también ofrece nuevas funciones al respecto.
Asegúrese de leer el registro de cambios de la API de iOS 6 en el sitio web de desarrolladores de Apple. Y compruebe las nuevas capacidades de AutoLayout
de iOS 6 .

Dicho esto, si realmente necesitas detectar el iPhone 5, simplemente puedes confiar en el tamaño de la pantalla .

[ [ UIScreen mainScreen ] bounds ].size.height

La pantalla del iPhone 5 tiene una altura de 568.
Puedes imaginar una macro, para simplificar todo esto:

#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )

El uso de fabscon épsilon está aquí para evitar errores de precisión al comparar puntos flotantes, como se señala en los comentarios de H2CO3.

Entonces, de ahora en adelante puedes usarlo en declaraciones estándar if/else:

if( IS_IPHONE_5 )
{}
else
{}

Editar - Mejor detección

Como afirman algunas personas, esto sólo detecta una pantalla panorámica , no un iPhone 5 real.

Es posible que las próximas versiones del iPod touch también tengan dicha pantalla, por lo que podremos utilizar otro conjunto de macros.

Cambiemos el nombre de la macro original IS_WIDESCREEN:

#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )

Y agreguemos macros de detección de modelos:

#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )
#define IS_IPOD   ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPod touch" ] )

De esta manera, podemos asegurarnos de tener un modelo de iPhone Y una pantalla ancha, y podemos redefinir la IS_IPHONE_5macro:

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

También tenga en cuenta que, como lo indica @LearnCocos2D, estas macros no funcionarán si la aplicación no está optimizada para la pantalla del iPhone 5 (falta la imagen [email protected] ), ya que el tamaño de la pantalla seguirá siendo 320x480 en tal caso. un caso.

No creo que esto pueda ser un problema, ya que no veo por qué querríamos detectar un iPhone 5 en una aplicación no optimizada.

IMPORTANTE: compatibilidad con iOS 8

En iOS 8, la boundspropiedad de la UIScreenclase ahora refleja la orientación del dispositivo .
Obviamente, el código anterior no funcionará de inmediato.

Para solucionar este problema, simplemente puede usar la nueva nativeBoundspropiedad, en lugar de bounds, ya que no cambiará con la orientación y se basa en un modo vertical.
Tenga en cuenta que las dimensiones nativeBoundsse miden en píxeles, por lo que para un iPhone 5 la altura será 1136 en lugar de 568.

Si también estás apuntando a iOS 7 o inferior, asegúrate de usar la detección de funciones, ya que llamar nativeBoundsantes de iOS 8 bloqueará tu aplicación:

if( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] )
{
    /* Detect using nativeBounds - iOS 8 and greater */
}
else
{
    /* Detect using bounds - iOS 7 and lower */
}

Puedes adaptar las macros anteriores de la siguiente manera:

#define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_WIDESCREEN_IOS8 ( fabs( ( double )[ [ UIScreen mainScreen ] nativeBounds ].size.height - ( double )1136 ) < DBL_EPSILON )
#define IS_WIDESCREEN      ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_WIDESCREEN_IOS8 : IS_WIDESCREEN_IOS7 )

Y obviamente, si necesitas detectar un iPhone 6 o 6 Plus, utiliza los tamaños de pantalla correspondientes.

Macmade avatar Sep 16 '2012 13:09 Macmade

Probado y diseñado para cualquier combinación de SDK y SO:

Rápido

Tipos de iPad agregados. El iPad 2 y el iPad mini son iPads sin retina. Mientras que el iPad Mini 2 y superior, el iPad 3, 4, el iPad Air, el Air 2, el Air 3 y el iPad Pro 9.7 tienen la misma resolución lógica de 1024. El iPad Pro tiene una longitud máxima de 1366 .

import UIKit

public enum DisplayType {
    case unknown
    case iphone4
    case iphone5
    case iphone6
    case iphone6plus
    case iPadNonRetina
    case iPad
    case iPadProBig
    static let iphone7 = iphone6
    static let iphone7plus = iphone6plus
}

public final class Display {
    class var width:CGFloat { return UIScreen.main.bounds.size.width }
    class var height:CGFloat { return UIScreen.main.bounds.size.height }
    class var maxLength:CGFloat { return max(width, height) }
    class var minLength:CGFloat { return min(width, height) }
    class var zoomed:Bool { return UIScreen.main.nativeScale >= UIScreen.main.scale }
    class var retina:Bool { return UIScreen.main.scale >= 2.0 }
    class var phone:Bool { return UIDevice.current.userInterfaceIdiom == .phone }
    class var pad:Bool { return UIDevice.current.userInterfaceIdiom == .pad }
    class var carplay:Bool { return UIDevice.current.userInterfaceIdiom == .carPlay }
    class var tv:Bool { return UIDevice.current.userInterfaceIdiom == .tv }
    class var typeIsLike:DisplayType {
        if phone && maxLength < 568 {
            return .iphone4
        }
        else if phone && maxLength == 568 {
                return .iphone5
        }
        else if phone && maxLength == 667 {
            return .iphone6
        }
        else if phone && maxLength == 736 {
            return .iphone6plus
        }
        else if pad && !retina {
            return .iPadNonRetina
        }
        else if pad && retina && maxLength == 1024 {
            return .iPad
        }
        else if pad && maxLength == 1366 {
            return .iPadProBig
        }
        return .unknown
    }
}

Véalo en acción https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

Nota: Si, por ejemplo, el iPhone 6 está en modo ampliado, la interfaz de usuario es una versión ampliada del iPhone 5. Estas funciones no determinan el tipo de dispositivo, sino el modo de visualización, por lo que el iPhone 5 es el resultado deseado en este ejemplo.

C objetivo

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)

#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_ZOOMED (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)

#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)

Uso: http://pastie.org/9687735

Nota: Si, por ejemplo, el iPhone 6 está en modo ampliado, la interfaz de usuario es una versión ampliada del iPhone 5. Estas funciones no determinan el tipo de dispositivo, sino el modo de visualización, por lo que el iPhone 5 es el resultado deseado en este ejemplo.

hfossli avatar Oct 31 '2012 11:10 hfossli

Solución realmente simple

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    if(result.height == 568)
    {
        // iPhone 5
    }
}
Samrat Mazumdar avatar Sep 25 '2012 17:09 Samrat Mazumdar

Ahora debemos tener en cuenta los tamaños de pantalla del iPhone 6 y 6Plus. Aquí hay una respuesta actualizada.

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    //its iPhone. Find out which one?

    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    else if(result.height == 568)
    {
        // iPhone 5
    }
    else if(result.height == 667)
    {
        // iPhone 6
    }
   else if(result.height == 736)
    {
        // iPhone 6 Plus
    }
}
else
{
     //its iPad
}

Alguna información útil

iPhone 6 Plus   736x414 points  2208x1242 pixels    3x scale    1920x1080 physical pixels   401 physical ppi    5.5"
iPhone 6        667x375 points  1334x750 pixels     2x scale    1334x750 physical pixels    326 physical ppi    4.7"
iPhone 5        568x320 points  1136x640 pixels     2x scale    1136x640 physical pixels    326 physical ppi    4.0"
iPhone 4        480x320 points  960x640 pixels      2x scale    960x640 physical pixels     326 physical ppi    3.5"
iPhone 3GS      480x320 points  480x320 pixels      1x scale    480x320 physical pixels     163 physical ppi    3.5"
Sam B avatar Sep 24 '2014 13:09 Sam B

Me tomé la libertad de poner la macro hecha por Mac en una función C y nombrarla correctamente porque detecta la disponibilidad de pantalla ancha y NO necesariamente el iPhone 5.

La macro tampoco detecta la ejecución en un iPhone 5 en caso de que el proyecto no incluya [email protected] . Sin la nueva imagen predeterminada, el iPhone 5 tendrá un tamaño de pantalla normal de 480x320 (en puntos). Por lo tanto, la verificación no es solo para la disponibilidad de pantalla ancha, sino también para que el modo de pantalla ancha esté habilitado .

BOOL isWidescreenEnabled()
{
    return (BOOL)(fabs((double)[UIScreen mainScreen].bounds.size.height - 
                                               (double)568) < DBL_EPSILON);
}
CodeSmile avatar Sep 21 '2012 14:09 CodeSmile