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?

Finn Gaida
fonte
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
Verifique este URL: stackoverflow.com/questions/4779221/…
ios_av
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 [email protected]), 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.

Macmade
fonte
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.

hfossli
fonte
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
    }
}
Samrat Mazumdar
fonte
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"
Sam B
fonte
é 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 [email protected] . 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);
}
LearnCocos2D
fonte
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 )
Gengibre
fonte
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)
Borbea
fonte
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))
OMGPOP
fonte
5
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
    // This is iPhone 5 screen
} else {
    // This is iPhone 4 screen
}
D-eptdeveloper
fonte
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.

zubko
fonte
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
    }
} 
Jeff Hay
fonte
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)
Bhavesh Dhaduk
fonte
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 )
valvoline
fonte
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;

}
Mubin Shaikh
fonte
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

     }
Nithin M Keloth
fonte
1

Confiar no tamanho está errado em muitos níveis. Que tal pedirmos ao sistema?

- (NSString *) getDeviceModel
{
    struct utsname systemInfo;
    uname(&systemInfo);
    return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}

Retirado da melhor maneira de detectar o tipo de hardware, iPhone4 ou iPhone5? , resposta edzio27.

3d0
fonte
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
Xeieshan
fonte
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");

}
Aritra Das
fonte
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
        }
William Hu
fonte
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)
}
Julian D.
fonte
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.

William T.
fonte
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
}
Laszlo
fonte
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;
}
Pawel Molodkin
fonte
-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) 
Vaibhav Sharma
fonte
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
Veja este link. stackoverflow.com/questions/25756589/…
Vaibhav Sharma
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