Como detectar o iPhone 5 (dispositivos widescreen)?


300

Acabei de atualizar para o XCode 4.5 GM e descobri que agora você pode aplicar o tamanho '4 "Retina' ao seu controlador de exibição no storyboard.

Agora, se eu quiser criar um aplicativo que seja executado no iPhone 4 e 5, é claro que preciso construir todas as janelas duas vezes, mas também preciso detectar se o usuário tem um iPhone com tela de 3,5 "ou 4" e aplicar o Visão.

Como devo fazer isso?


2
Você não precisa criar todas as "janelas" duas vezes. Somente aqueles que devem corresponder exatamente ao tamanho da tela terão que ser reencaminhados. A solução parece bastante óbvia, basta verificar as dimensões da janela e adicionar uma decisão de caso com base no tamanho retornado.
Até

1
Bem, basicamente isso é verdade, mas eu quero usar o tamanho extra da tela de uma maneira completamente diferente, como você poderia fazer com uma tela de paisagem.
Finn Gaida


Esta pergunta deve ser atualizada de acordo com os novos dispositivos? Por exemplo, "Como detectar o dispositivo iOS pelo tamanho da tela"?
Hfossli

Respostas:


467

Primeiro, você não deve reconstruir todas as suas visualizações para caber em uma nova tela, nem usar diferentes visualizações para diferentes tamanhos de tela.

Use o redimensionamento automático recursos de do iOS, para que suas visualizações possam ajustar e adaptar qualquer tamanho de tela.

Isso não é muito difícil, leia alguma documentação sobre isso. Isso economizará muito tempo.

O iOS 6 também oferece novos recursos sobre isso.
Certifique-se de ler o log de alterações da API do iOS 6 no site da Apple Developer.
E verifique os novos recursos do iOS 6 AutoLayout .

Dito isto, se você realmente precisa detectar o iPhone 5, pode simplesmente confiar no tamanho da tela .

[ [ UIScreen mainScreen ] bounds ].size.height

A tela do iPhone 5 tem uma altura de 568.
Você pode imaginar uma macro para simplificar tudo isso:

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

O uso de fabs com o epsilon está aqui para evitar erros de precisão ao comparar pontos flutuantes, conforme apontado nos comentários de H2CO3.

Portanto, a partir de agora você pode usá-lo nas instruções if / else padrão:

if( IS_IPHONE_5 )
{}
else
{}

Editar - Melhor detecção

Como afirmado por algumas pessoas, isso se limita a detectar uma widescreen , não um iPhone 5 real.

As próximas versões do iPod touch talvez também tenham essa tela, para que possamos usar outro conjunto de macros.

Vamos renomear a macro original IS_WIDESCREEN:

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

E vamos adicionar macros de detecção de modelo:

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

Dessa forma, podemos garantir que temos um modelo de iPhone E uma tela widescreen e podemos redefinir a IS_IPHONE_5macro:

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

Observe também que, conforme declarado pelo @ LearnCocos2D, essas macros não funcionarão se o aplicativo não for otimizado para a tela do iPhone 5 (sem a imagem Default-568h@2x.png), pois o tamanho da tela ainda será 320x480. um caso.

Eu não acho que isso possa ser um problema, pois não vejo por que queremos detectar um iPhone 5 em um aplicativo não otimizado.

IMPORTANTE - suporte para iOS 8

No iOS 8, a boundspropriedade da UIScreenclasse agora reflete a orientação do dispositivo .
Então, obviamente, o código anterior não funcionará imediatamente.

Para corrigir isso, você pode simplesmente usar a nova nativeBoundspropriedade, em vez de bounds, pois ela não muda com a orientação e como se baseia no modo de retrato.
Observe que as dimensões de nativeBoundssão medidas em pixels; portanto, para um iPhone 5, a altura será 1136 em vez de 568.

Se você também está segmentando o iOS 7 ou inferior, use a detecção de recursos, pois as chamadas nativeBoundsanteriores ao iOS 8 causam um travamento no aplicativo:

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

Você pode adaptar as macros anteriores da seguinte maneira:

#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 )

E, obviamente, se você precisar detectar um iPhone 6 ou 6 Plus, use os tamanhos de tela correspondentes.


7
Isso está errado, você terá que usar ##define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == 568 )
Fabian Kreiser

28
@ H2CO3: Observe que a comparação para DBL_EPSILONnão é necessária aqui e que a ==comparação não falhará: é necessário fazer comparação usando diferenças dessa maneira se o valor do ponto flutuante não puder ser expresso como um número exato (como 1.0/3.0*3.0por exemplo). Leia este artigo para obter mais informações;)
AliSoftware

2
esta resposta não está correta. por que conseguiu tantos polegares para cima? você não pode usar apenas a altura para determinar se é widescreen. cara ...
OMGPOP

5
Devo acrescentar: Se você deseja que isso funcione com o simulador, use: #define IS_IPHONE (([[modelo do UIDevice currentDevice]]] isEqualToString: @ "iPhone"]) || ([[modelo do UIDevice currentDevice]] isEqualToString: @ "iPhone Simulator"]))
david

31
Essa resposta é loucura. A recomendação de não comparar esse tipo específico de carros alegóricos (que na realidade são - e se você sabe que a Apple deve saber que sempre será-- números inteiros) com == é um absurdo e complica demais as coisas. Além disso, acho melhor usar o UI_USER_INTERFACE_IDIOM () para a detecção do iPhone, pois funciona bem no dispositivo e no simulador (e pode ser mais rápido que a abordagem do UIDevice). Isso só funciona bem e é a maneira mais simples para ler: #define IS_IPHONE5 (UI_USER_INTERFACE_IDIOM () == UIUserInterfaceIdiomPhone && [UIScreen mainScreen] .bounds.size.height == 568)
Ricardo Sanchez-Saez

232

Testado e projetado para qualquer combinação de SDK e SO:

Rápido

Tipos de iPad adicionados. O iPad 2 e o iPad mini são iPads sem retina. Enquanto o iPad Mini 2 e superior, o iPad 3, 4, o iPad Air, o Air 2, o Air 3 e o iPad Pro 9.7 têm a mesma resolução lógica de 1024. O iPad Pro tem o comprimento máximo de 1366. Referência

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
    }
}

Veja em ação https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

Nota: Se, por exemplo, o iPhone 6 estiver no modo ampliado, a interface do usuário será uma versão ampliada do iPhone 5. Essas funções não determinam o tipo de dispositivo, mas o modo de exibição, portanto, o iPhone 5 é o resultado desejado neste exemplo.

Objetivo-C

#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: Se, por exemplo, o iPhone 6 estiver no modo ampliado, a interface do usuário será uma versão ampliada do iPhone 5. Essas funções não determinam o tipo de dispositivo, mas o modo de exibição, portanto, o iPhone 5 é o resultado desejado neste exemplo.


1
O iPhone 5 reportará um tamanho de tela normal de 480 x 320, sem a nova imagem padrão. Para mim, esse é um comportamento desejado.
Hfossli 03/11/2012

3
Uma adição possivelmente útil é #define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)o que irá ajudar a determinar a diferença entre ambos iPhone4 e iPhone5 e iPad Retina e não-retina
bshirley

1
Discordo. Eu acho que a terminologia 'widescreen' deve ser deixada de fora, pois está rapidamente desatualizada.
Hfossli 9/09/14

1
@Dvole é assim que o iOS 8 se comporta. Use SCREEN_MAX_LENGTHpara obter 568 em todas as rotações no iPhone 5.
hfossli

1
@MattParkins Eu sugeriria o uso de verificações de modelo mais robustas stackoverflow.com/questions/13366976/… .
Hfossli

69

Solução realmente simples

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    if(result.height == 568)
    {
        // iPhone 5
    }
}

1
haha curto e simpel, fez o mesmo :) bate para manter as despesas baixas! colocar coisas em uma macro não é um desafio ...
benjamin.ludwig

2
Bem, não colocar as coisas em funções de macro ou está propenso a não ser seco ... A partir do momento que você precisa fazer essa verificação mais de uma vez ...
hfossli

Sim, mas defina macro como mostrado acima, é mais conveniente e fácil, você não precisa colar e escrever isso se ... sempre.
Resty

Obrigado, você salvou minha vida: D, mas não sei por que Macro: #define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] limites]] .size.height == 568.0) ==> Não está funcionando no simulador iOS 7.1, antes que ainda estou trabalhando no XCode 4.6. OMG iOS 7.1 e Xcode 5
Linh Nguyen 07/04

atualizados resposta abaixo a conta para iPhone 6 e 6 mais tamanhos de tela
Sam B

28

Agora precisamos contabilizar os tamanhos de tela do iPhone 6 e 6Plus. Aqui está uma resposta atualizada

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
}

Algumas informações úteis

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"

é simplesmente não funciona para mim iPhone 5 decidido como 4 iPhone 6+ não decidiu em tudo Oh, eu tenho que estou na paisagem que eu deveria mudar de altura com largura :)
ColdSteel

Se seu aplicativo está em modo paisagem, em seguida, certifique-se de mudar result.height para result.width
Sam B

hmm .. no iPhone 4 (iOS 6.0) ele não trocou :( poderia ser um prob iOS 6.0 ou um iPhone 4?
ColdSteel

Ok, eu verifiquei a vista trocados somente no iOS 8 e maior
ColdSteel

iPhone 6 dando altura = 568
MaxEcho

15

Tomei a liberdade de colocar a macro do Macmade em uma função C e nomeie-a corretamente, pois detecta a disponibilidade de widescreen e NÃO necessariamente o iPhone 5.

A macro também não detecta a execução em um iPhone 5, caso o projeto não inclua o Default-568h@2x.png . Sem a nova imagem padrão, o iPhone 5 reportará um tamanho de tela normal de 480x320 (em pontos). Portanto, a verificação não é apenas para disponibilidade de tela widescreen, mas também para o modo widescreen .

BOOL isWidescreenEnabled()
{
    return (BOOL)(fabs((double)[UIScreen mainScreen].bounds.size.height - 
                                               (double)568) < DBL_EPSILON);
}

Eu ainda prefiro as macros, por razões de desempenho. Por favor, veja a edição da minha resposta. Também verifica o modelo.
Macmade

1
Você também está certo ao dizer que um iPhone 5 reportará um tamanho de tela normal de 480x320, sem a nova imagem padrão. Mas acho que não faz sentido detectar um iPhone 5 em um aplicativo não otimizado. :)
Macmade

@ Macmade De fato, não faz sentido, mas é bom ter em mente se a detecção não funcionar. Além disso, as funções podem ser inlined. Eles também serão informados onde o otimizador do compilador acha que é uma boa ideia e onde pode saber que é permitido (por exemplo, a função está no mesmo módulo). Implementar coisas como essa por meio de uma função às vezes pode trazer verificação de tipo adicional.
Ivan Vučica

4
A questão relacionada ao desempenho é: por que você executou essa verificação milhares de vezes durante o loop de renderização? Caso contrário, o desempenho é um não problema e clareza e evita efeitos colaterais de maior importância.
LearnCocos2D

Eu dei um +1 para isso porque gosto mais da função separada do que de uma macro, mas preciso ressaltar que ela não está realmente correta ou completa. Para detectar widescreen, não olhe para a altura da tela. Em vez disso, observe a proporção e retorne true somente se a proporção for maior ou igual a 16: 9.
Todd Lehman

11

Aqui estão nossos códigos, teste passado no ios7 / ios8 para iphone4, iphone5, ipad, iphone6, iphone6p, independentemente de dispositivos ou simuladores:

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) // iPhone and       iPod touch style UI

#define IS_IPHONE_5_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0f)
#define IS_IPHONE_6_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0f)
#define IS_IPHONE_6P_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS7 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height < 568.0f)

#define IS_IPHONE_5_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 568.0f)
#define IS_IPHONE_6_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 667.0f)
#define IS_IPHONE_6P_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) == 736.0f)
#define IS_IPHONE_4_AND_OLDER_IOS8 (IS_IPHONE && ([[UIScreen mainScreen] nativeBounds].size.height/[[UIScreen mainScreen] nativeScale]) < 568.0f)

#define IS_IPHONE_5 ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_5_IOS8 : IS_IPHONE_5_IOS7 )
#define IS_IPHONE_6 ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_6_IOS8 : IS_IPHONE_6_IOS7 )
#define IS_IPHONE_6P ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_6P_IOS8 : IS_IPHONE_6P_IOS7 )
#define IS_IPHONE_4_AND_OLDER ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_IPHONE_4_AND_OLDER_IOS8 : IS_IPHONE_4_AND_OLDER_IOS7 )

Estou testando em um iPhone 6P e minha instrução if está caindo na condição IS_IPHONE_5? Como isso pode ser, seu código parece ser bom? Fiz uma cópia direta e colei com um simples if / else e sei que meu telefone é um iOS 6 mais executando o 8.3.
whyoz

7

Usei a resposta de hfossli e a traduzi para Swift

let IS_IPAD = UIDevice.currentDevice().userInterfaceIdiom == .Pad
let IS_IPHONE = UIDevice.currentDevice().userInterfaceIdiom == .Phone
let IS_RETINA = UIScreen.mainScreen().scale >= 2.0

let SCREEN_WIDTH = UIScreen.mainScreen().bounds.size.width
let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
let SCREEN_MAX_LENGTH = max(SCREEN_WIDTH, SCREEN_HEIGHT)
let SCREEN_MIN_LENGTH = min(SCREEN_WIDTH, SCREEN_HEIGHT)

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

6

essa é a macro para o meu projeto cocos2d. deve ser o mesmo para outros aplicativos.

#define WIDTH_IPAD 1024
#define WIDTH_IPHONE_5 568
#define WIDTH_IPHONE_4 480
#define HEIGHT_IPAD 768
#define HEIGHT_IPHONE 320

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)

//width is height!
#define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_5 )
#define IS_IPHONE_4 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_4 )

#define cp_ph4(__X__, __Y__) ccp(cx_ph4(__X__), cy_ph4(__Y__))
#define cx_ph4(__X__) (IS_IPAD ? (__X__ * WIDTH_IPAD / WIDTH_IPHONE_4) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPHONE_4) : (__X__)))
#define cy_ph4(__Y__) (IS_IPAD ? (__Y__ * HEIGHT_IPAD / HEIGHT_IPHONE) : (__Y__))

#define cp_pad(__X__, __Y__) ccp(cx_pad(__X__), cy_pad(__Y__))
#define cx_pad(__X__) (IS_IPAD ? (__X__) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPAD) : (__X__ * WIDTH_IPHONE_4 / WIDTH_IPAD)))
#define cy_pad(__Y__) (IS_IPAD ? (__Y__) : (__Y__ * HEIGHT_IPHONE / HEIGHT_IPAD))

5
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
    // This is iPhone 5 screen
} else {
    // This is iPhone 4 screen
}

3

No Swift, projeto iOS 8+, eu gosto de fazer uma extensão UIScreen, como:

extension UIScreen {

    var isPhone4: Bool {
        return self.nativeBounds.size.height == 960;
    }

    var isPhone5: Bool {
        return self.nativeBounds.size.height == 1136;
    }

    var isPhone6: Bool {
        return self.nativeBounds.size.height == 1334;
    }

    var isPhone6Plus: Bool {
        return self.nativeBounds.size.height == 2208;
    }

}

(NOTA: nativeBoundsestá em pixels).

E então o código será como:

if UIScreen.mainScreen().isPhone4 {
    // do smth on the smallest screen
}

Portanto, o código deixa claro que essa é uma verificação para a tela principal, não para o modelo do dispositivo.


2

Tomando emprestado a resposta de Samrat Mazumdar, aqui está um método curto que estima o tamanho da tela do dispositivo. Funciona com os dispositivos mais recentes, mas pode falhar em dispositivos futuros (como todos os métodos de adivinhação). Também ficará confuso se o dispositivo estiver sendo espelhado (retorna o tamanho da tela do dispositivo, não o tamanho da tela espelhada)

#define SCREEN_SIZE_IPHONE_CLASSIC 3.5
#define SCREEN_SIZE_IPHONE_TALL 4.0
#define SCREEN_SIZE_IPAD_CLASSIC 9.7

+ (CGFloat)screenPhysicalSize
{
    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    {
        CGSize result = [[UIScreen mainScreen] bounds].size;
        if (result.height < 500)
            return SCREEN_SIZE_IPHONE_CLASSIC;  // iPhone 4S / 4th Gen iPod Touch or earlier
        else
            return SCREEN_SIZE_IPHONE_TALL;  // iPhone 5
    }
    else
    {
        return SCREEN_SIZE_IPAD_CLASSIC; // iPad
    }
} 

Precisa de revisão para o iPad mini que, eu não acredito que você será capaz de determinar nesta mansão.
Daniel

Sim, o iPad mini tem a mesma resolução que o iPad2, portanto esse método não funciona para isso. Não tenho certeza como lidar com esse caso agora ...
Jeff Hay

1
Você não deveria. Você pode verificar o identificador do dispositivo para comprar o "iPad 2,5" e também verificar as opções 2,6 e 2,7 - a versão apenas para wifi, gsm e CDMA. Mas isso significa que o próximo iPad mini será lançado e você precisará atualizar também o código rígido para esses identificadores, que você não pode conhecer de antemão. Você não pode saber continuamente quando está em um iPad mini, porque realmente não deve tentar "otimizar" para a tela menor
Daniel

2

Eu acho que seria bom se essa macro funcionasse no dispositivo e no simulador, abaixo está a solução.

#define IS_WIDESCREEN (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE (([[[UIDevice currentDevice] model] isEqualToString:@"iPhone"]) || ([[[UIDevice currentDevice] model] isEqualToString: @"iPhone Simulator"]))
#define IS_IPOD   ([[[UIDevice currentDevice]model] isEqualToString:@"iPod touch"])
#define IS_IPHONE_5 ((IS_IPHONE || IS_IPOD) && IS_WIDESCREEN)

2

Descobri que as respostas não incluem um caso especial para simuladores.

#define IS_WIDESCREEN ( [ [ UIScreen mainScreen ] bounds ].size.height == 568  )
#define IS_IPHONE ([[ [ UIDevice currentDevice ] model ] rangeOfString:@"iPhone"].location != NSNotFound)
#define IS_IPAD ([[ [ UIDevice currentDevice ] model ] rangeOfString:@"iPad"].location != NSNotFound)
#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

2
+(BOOL)isDeviceiPhone5
{
    BOOL iPhone5 = FALSE;

    CGRect screenBounds = [[UIScreen mainScreen] bounds];
    if (screenBounds.size.height == 568)
    {
        // code for 4-inch screen
        iPhone5 = TRUE;
    }
    else
    {
        iPhone5 = FALSE;
        // code for 3.5-inch screen
    }
    return iPhone5;

}

iPhone5 = FALSE;é desnecessário porque a variável já esse valor se não mudou
Mcont

1
CGFloat height = [UIScreen mainScreen].bounds.size.height;

NSLog(@"screen soze is %f",height);

  if (height>550) {

          // 4" screen-do some thing
     }

  else if (height<500) {

        // 3.5 " screen- do some thing

     }


1

Dessa forma, você pode detectar a família de dispositivos.

    #import <sys/utsname.h>
    NSString* deviceName()
    {
        struct utsname systemInformation;
        uname(&systemInformation);
        NSString *result = [NSString stringWithCString:systemInformation.machine
                                              encoding:NSUTF8StringEncoding];
        return result;
    }

    #define isIPhone5  [deviceName() rangeOfString:@"iPhone5,"].location != NSNotFound
    #define isIPhone5S [deviceName() rangeOfString:@"iPhone6,"].location != NSNotFound

1

Se o projeto for criado usando o Xcode 6, use o código abaixo mencionado para detectar os dispositivos.

printf("\nDetected Resolution : %d x %d\n\n",(int)[[UIScreen mainScreen] nativeBounds].size.width,(int)[[UIScreen mainScreen] nativeBounds].size.height);

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
    if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
    {
        if([[UIScreen mainScreen] nativeBounds].size.height == 960 || [[UIScreen mainScreen] nativeBounds].size.height == 480){
            printf("Device Type : iPhone 4,4s ");

        }else if([[UIScreen mainScreen] nativeBounds].size.height == 1136){
            printf("Device Type : iPhone 5,5S/iPod 5 ");

        }else if([[UIScreen mainScreen] nativeBounds].size.height == 1334){
            printf("Device Type : iPhone 6 ");

        }else if([[UIScreen mainScreen] nativeBounds].size.height == 2208){
            printf("Device Type : iPhone 6+ ");

        }
    }
}else{
    printf("Device Type : iPad");
}

Se o projeto foi criado no Xcode 5 e aberto no Xcode 6, use o código abaixo mencionado para detectar os dispositivos (esse código funcionará se nenhuma imagem de inicialização do iPhone 6,6+ estiver atribuída)

printf("\nDetected Resolution : %d x %d\n\n",(int)[[UIScreen mainScreen] nativeBounds].size.width,(int)[[UIScreen mainScreen] nativeBounds].size.height);
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
    if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
    {
       if([[UIScreen mainScreen] nativeBounds].size.height == 960 || [[UIScreen mainScreen] nativeBounds].size.height == 480){
            printf("Device Type : iPhone 4,4s");
            appType=1;
        }else if([[UIScreen mainScreen] nativeBounds].size.height == 1136 || [[UIScreen mainScreen] nativeBounds].size.height == 1704){
            printf("Device Type : iPhone 5,5S,6,6S/iPod 5 ");
            appType=3;
        }
    }
}else{
    printf("Device Type : iPad");
    appType=2;
}

Se você ainda estiver usando o Xcode 5 juntos, use o código a seguir para detectar os dispositivos (o iPhone 6 e 6+ não serão detectados)

printf("\nDetected Resolution : %d x %d\n\n",(int)[[UIScreen mainScreen] bounds].size.width,(int)[[UIScreen mainScreen] bounds].size.height);
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
    if ([[UIScreen mainScreen] respondsToSelector: @selector(scale)])
    {
        CGSize result = [[UIScreen mainScreen] bounds].size;
        CGFloat scale = [UIScreen mainScreen].scale;
        result = CGSizeMake(result.width * scale, result.height * scale);
        if(result.height == 960 || result.height == 480){
            printf("Device Type : iPhone 4,4S ");

        }else if(result.height == 1136){
            printf("Device Type : iPhone 5s/iPod 5");

        }
    }
}else{
    printf("Device Type : iPad");

}

1
  1. Adicione um 'Novo arquivo Swift' -> AppDelegateEx.swift

  2. adicione uma extensão a AppDelegate

    import UIKit
    extension AppDelegate {
         class func isIPhone5 () -> Bool{
             return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 568.0
        }
        class func isIPhone6 () -> Bool {
            return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 667.0
        }
        class func isIPhone6Plus () -> Bool {
            return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 736.0
        }  
    }
  3. uso:

        if AppDelegate.isIPhone5() {
            collectionViewTopConstraint.constant = 2
        }else if AppDelegate.isIPhone6() {
            collectionViewTopConstraint.constant = 20
        }

1

No Swift 3, você pode usar minha classe simples KRDeviceType.

https://github.com/ulian-onua/KRDeviceType

É bem documentado e suporta operadores ==,> =, <=.

Por exemplo, para detectar se o dispositivo tem limites de iPhone 6 / 6s / 7, você pode apenas usar a próxima comparação:

if KRDeviceType() == .iPhone6 {
// Perform appropiate operations
}

Para detectar se o dispositivo possui limites do iPhone 5 / 5S / SE ou anterior (iPhone 4s), você pode usar a próxima comparação:

if KRDeviceType() <= .iPhone5 {   //iPhone 5/5s/SE of iPhone 4s
// Perform appropiate operations (for example, set up constraints for those old devices)
}

1

Isso já foi respondido centenas de vezes, mas essa solução funcionou melhor para mim e ajudou a solucionar o problema quando novos dispositivos são introduzidos e eu não tenho um tamanho definido.

Ajudante do Swift 5:

extension UIScreen {
    func phoneSizeInInches() -> CGFloat {
        switch (self.nativeBounds.size.height) {
        case 960, 480:
            return 3.5  //iPhone 4
        case 1136:
            return 4    //iPhone 5
        case 1334:
            return 4.7  //iPhone 6
        case 2208:
            return 5.5  //iPhone 6 Plus
        case 2436:
            return 5.8  //iPhone X
        case 1792:
            return 5.5  //iPhone XR
        case 2688:
            return 6.5  //iPhone XS Max
        default:
            let scale = self.scale
            let ppi = scale * 163
            let width = self.bounds.size.width * scale
            let height = self.bounds.size.height * scale
            let horizontal = width / ppi, vertical = height / ppi
            let diagonal = sqrt(pow(horizontal, 2) + pow(vertical, 2))
            return diagonal
        }
    }
}

Isso ocorre porque é fácil memorizar os tamanhos de polegada de um telefone, como dispositivo de "5,5 polegadas" ou "4,7 polegadas", mas é difícil lembrar os tamanhos exatos de pixels.

if UIScreen.main.phoneSizeInInches() == 4 {
  //do something with only 4 inch iPhones
}

Isso também lhe dá a oportunidade de fazer algo assim:

if UIScreen.main.phoneSizeInInches() < 5.5 {
  //do something all iPhones smaller than the plus
}

O padrão: tenta usar o tamanho e a escala da tela para tentar calcular as polegadas diagonais. Isso acontece se algum novo tamanho de dispositivo aparecer, ele tentará o seu melhor para determinar e o código, como o último exemplo, ainda deve funcionar.


0

use o seguinte código:

CGFloat screenScale = [[UIScreen mainScreen] scale];

CGRect screenBounds = [[UIScreen mainScreen] bounds]; 

CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale); 

if (screenSize.height==1136.000000)
{ 
    // Here iPhone 5 View

    // Eg: Nextview~iPhone5.Xib
} else {
   // Previous Phones 

   // Eg : Nextview.xib
}

0

Aqui está o teste correto do dispositivo, sem depender da orientação

- (BOOL)isIPhone5
{
    CGSize size = [[UIScreen mainScreen] bounds].size;
    if (MIN(size.width,size.height) == 320 && MAX(size.width,size.height == 568)) {
        return YES;
    }
    return NO;
}

-2

Usado para detectar dispositivos iPhone e iPad de todos os versons.

#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0) 

iPhone 6 não tem tela retina?
vikingosegundo 28/09

O iPhone6 ​​possui a tela ratina (@ 2X). e o iPhone6 ​​plus possui a tela HD (@ 3X).
Vaibhav Sharma

Então, se testado IS_RETINAem um iPhone 6 plus, o código 1x é executado?
Vikingosegundo


1
você não entende: suas regras cederão @1x, onde cederão @3x. de qualquer maneira: como você está simplesmente copiando e colando: -1
vikingosegundo 6/14
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.