How to detect iPhone 5 (widescreen devices)?
Asked Answered
C

24

302

I've just upgraded to Xcode 4.5 GM and found out that you can now apply the '4" Retina' size to your view controller in the storyboard.

Now if I want to create an application that runs on both iPhone 4 and 5, of course I have to build every window twice, but I also have to detect whether the user has an iPhone with 3.5" or 4" screen and then apply the view.

How should I do that?

Conover answered 16/9, 2012 at 12:50 Comment(4)
You do not have to build every "window" twice. Only those that are supposed to exactly match the screen size will have to be relayouted. The solution seems rather obvious, simply check for the window dimensions and add a case decision based on the returned size.Oshiro
Well, basically that's true, but I want to use the extra screen size in a completely different way, like you could do with a landscape screen.Conover
Check this URL: #4779721Vegetarianism
Should this question be updated in accordance with new devices? E.g. "How to detect iOS device by screen size"?Anemology
E
467

First of all, you shouldn't rebuild all your views to fit a new screen, nor use different views for different screen sizes.

Use the auto-resizing capabilities of iOS, so your views can adjust, and adapt any screen size.

That's not very hard, read some documentation about that. It will save you a lot of time.

iOS 6 also offers new features about this.
Be sure to read the iOS 6 API changelog on Apple Developer website.
And check the new iOS 6 AutoLayout capabilities.

That said, if you really need to detect the iPhone 5, you can simply rely on the screen size.

[ [ UIScreen mainScreen ] bounds ].size.height

The iPhone 5's screen has a height of 568.
You can imagine a macro, to simplify all of this:

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

The use of fabs with the epsilon is here to prevent precision errors, when comparing floating points, as pointed in the comments by H2CO3.

So from now on you can use it in standard if/else statements:

if( IS_IPHONE_5 )
{}
else
{}

Edit - Better detection

As stated by some people, this does only detect a widescreen, not an actual iPhone 5.

Next versions of the iPod touch will maybe also have such a screen, so we may use another set of macros.

Let's rename the original macro IS_WIDESCREEN:

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

And let's add model detection macros:

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

This way, we can ensure we have an iPhone model AND a widescreen, and we can redefine the IS_IPHONE_5 macro:

#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )

Also note that, as stated by @LearnCocos2D, this macros won't work if the application is not optimised for the iPhone 5 screen (missing the [email protected] image), as the screen size will still be 320x480 in such a case.

I don't think this may be an issue, as I don't see why we would want to detect an iPhone 5 in a non-optimized app.

IMPORTANT - iOS 8 support

On iOS 8, the bounds property of the UIScreen class now reflects the device orientation.
So obviously, the previous code won't work out of the box.

In order to fix this, you can simply use the new nativeBounds property, instead of bounds, as it won't change with the orientation, and as it's based on a portrait-up mode.
Note that dimensions of nativeBounds is measured in pixels, so for an iPhone 5 the height will be 1136 instead of 568.

If you're also targeting iOS 7 or lower, be sure to use feature detection, as calling nativeBounds prior to iOS 8 will crash your app:

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

You can adapt the previous macros the following way:

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

And obviously, if you need to detect an iPhone 6 or 6 Plus, use the corresponding screen sizes.

Erminois answered 16/9, 2012 at 13:8 Comment(32)
This is wrong, you'll have to use #define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == 568 )Casease
Comparing floating-point numbers will fail. Why not check for height > 500 instead?Slily
@H2CO3 Ok, added a safety check for floats. height > 500 will work only if you don't have an universal app, otherwise, you'll also have to detect the model using UIDevice to see if it's an iPhone or an iPad.Erminois
@Erminois of course :) But it's still better than comparing floats using ==. What's convenient is that there's the iPhone/iPad limit between 568 and 768. So basically, you can use 3 checks: if (h < 500) { iPhone <= 4S } else if (h < 600) { iPhone 5 } else { iPad }.Slily
@H2CO3 Sure, but let's wait for the iPad mini dimensions, if there's such a thing... ; )Erminois
@Erminois is this answer done, or do I have to read the comments too? When answer is completed, please add some text to say that you've incorporated (or rebuffed) the comments, kindly. Thanks and +1.Manutius
@H2CO3 : Note that the comparison to DBL_EPSILON is not necessary here, and that the == comparison will not fail: it is only necessary to do comparison using differences this way if the floating point value cannot be expressed as an exact number (like 1.0/3.0*3.0 for example). Read this article for more info ;)Shotton
@Shotton yes, and I didn't suggest using an epsilon value. But as a general rule, I don't like comparing floats using == - it might (should!) work for these numbers, but not for others, and I don't really have envy to think about it every single time I compare floating point numbers - I just disuse == and != and that's safe and consistent.Slily
@H2CO3 why not just convert both operands to double: #define IS_IPHONE_5 ( (double)([ [ UIScreen mainScreen ] bounds ].size.height) == (double) 568 ) And both sides are 568 represented in double and it should not failArbutus
@Unicode: because that's ugly. (And inconsistent. I don't wanna keep trying to figure out when fp comparison works and when it doesn't.)Slily
@H2CO3 What's wrong with #define IS_IPHONE_5 ( (int)([ [ UIScreen mainScreen ] bounds ].size.height) == 568 )? You expect the mainScreen bounds to always be equivalent to an integer value anyway...Yila
@H2CO3 Point. Hmm. It'd be nice if Apple would just give us a straightforward way to determine this, like (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) and (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)...since the iPhone 5 is in many ways a new device to design for. I just found out there's no automatic extension for it either (like @2x etc.) But oh well, we can create these things ourselves even if they will be less pretty than a native solution!Yila
" I just found out there's no automatic extension for it either (like @2x etc.)" There is. Append -568h to the filename.Slily
One note where this DOESN'T work: if your app doesn't natively support the iPhone 5, the IS_IPHONE_5 check will return 0 even if the app is running on an iPhone 5. In cases where you haven't added the [email protected] to your project the screen size will be that of a regular Retina phone (480 not 568).Fugleman
@H2CO3 Then this answer is incorrect? https://mcmap.net/q/101701/-iphone-5-what-naming-convention-the-new-images-have-to-follow I would be so glad if that were the case...Yila
@LearnCocos2D Aha, so that Default image is the flag which tells the app whether or not it supports the iPhone 5 screen size or not? Thanks for the info--was curious about that.Yila
Well, my app was 480 on the iPhone 5 Simulator with black bars on both sides. Then I added the [email protected], restarted and I got fullscreen 568 points. So yep, that's it. :)Fugleman
Btw, I'm hard pressed not to call this "detect iPhone 5" because it really is a method that detects 16:9 aspect ratio. Future iPhones and iPod touches will very likely have the same screen resolution, but won't be "iPhone 5" models.Fugleman
Answer has been edited to also detect the actual model, to ensure it's an iPhone.Erminois
this answer is not correct. why did it get so many thumbs up? you can't use only the height to determine whether it's widescreen. dude...Chance
@Chance Please read the full answer, and the comments. As stated, it detects a widescreen AND an iPhone model.Erminois
When I try to use the IS_WIDESCREEN macro above, Xcode isn't having it: "Token is not a valid binary operator in a preprocessor subexpression." It doesn't say which token, but I think it's pointing at fabs().Heathcote
May I add: If you want this to work with the simulator use this: #define IS_IPHONE ( ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] ) || ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone Simulator" ] ) )Anastassia
This answer is madness. This stuff about recommending not comparing these particular kind of floats (which in reality are --and if you know Apple should know that always will be-- integers) with == is nonsense and overcomplicates things. Also, I think it's better to use UI_USER_INTERFACE_IDIOM() for iPhone detection as it works fine both on the device and simulator (and it might be faster than the UIDevice approach). This just works fine and is way simpler to read: #define IS_IPHONE5 (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone && [UIScreen mainScreen].bounds.size.height==568)Ahem
Why use "[[UIDevice currentDevice] model]" and not "UI_USER_INTERFACE_IDIOM()"?Anemology
Why is this a macro? This should be a function.Lazybones
Some of the other answers are much more efficient and elegant than all the stuff used in this answer. I've got several apps on the app store that are using techniques in the other answers here, and they all work well and it is much simpler, cleaner code.Inception
> Use the auto-resizing capabilities of iOS, so your views can adjust, and adapt any screen size. I have to say this is not really true at all. If you're using IB the tools are terrible for this in anything but extremely simple cases.Kenward
No longer works for ios8 in landscape mode, i believe because the orientation has to be taken into considerationLost
@Chiquis See the edit at the end of the answer for iOS 8 compatibility.Erminois
@Erminois Thanks, had to do this myself but your macro looks prettier.Lost
dont do that nativeBounds madness -- just include the right launch images and bounds will work fineMelancholia
A
232

Tested and designed for any combination of SDK and OS:

Swift

Added iPad types. iPad 2 and iPad mini are non-retina iPads. While iPad Mini 2 & above, iPad 3, 4, iPad Air, Air 2, Air 3, and iPad Pro 9.7 have same logical resolution of 1024. iPad Pro has maxLength of 1366. Reference

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

See it in action https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346

Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.

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

Usage: http://pastie.org/9687735

Note: If e.g. iPhone 6 is in zoomed mode the UI is a zoomed up version of iPhone 5. These functions is not determining device type, but display mode thus iPhone 5 is the desired result in this example.

Anemology answered 31/10, 2012 at 11:1 Comment(9)
iPhone 5 will report a regular 480x320 screen size, without the new default image. To me this is wanted behavior.Anemology
A possibly useful addition is #define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0) which will help determine the difference between both iPhone4 and iPhone5 and iPad Retina and non-retinaExcoriation
A possibly useful addition is #define IS_WIDESCREEN ([[UIScreen mainScreen] bounds].size.height == 568) and then: #define IS_IPHONE_5 (IS_IPHONE && IS_WIDESCREEN)Groyne
I disagree. I think the 'widescreen'-terminology should be left out as it is quickly outdated.Anemology
This does not work - iphone 5 in landscape returns 320Hydrosphere
@Hydrosphere that's how iOS 8 behaves. Use SCREEN_MAX_LENGTH to get 568 in all rotations on iPhone 5.Anemology
an IS_IPAD_MINI would be nice. Any ideas?Zielsdorf
@MattParkins I would suggest using more robust model checks #13367476.Anemology
@Anemology thanks for explain iOS 8 rotation issues. One more macros for iPad Pro: #define IS_IPAD_PRO (IS_IPAD && SCREEN_MAX_LENGTH == 1366.0) :-)Xenos
L
69

Really simple solution

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.height == 480)
    {
        // iPhone Classic
    }
    if(result.height == 568)
    {
        // iPhone 5
    }
}
Lawhorn answered 25/9, 2012 at 17:20 Comment(5)
haha short and simpel, did the same :) thumps up for keeping overhead low! putting stuff in a macro isn't a challenge...Laconia
Well not putting things in macro or functions is prone not to be DRY... From the moment you need to do this check more than once...Anemology
Yup, but define macro as shown above, is more convenient and easy, u don't need to paste write this if... every time.Photooffset
Thanks, You saved my life :D, But I don't know why Macro:#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0) ==> Not working in simulator iOS 7.1, before that I still working on XCode 4.6. OMG iOS 7.1 & Xcode 5Meredi
updated answer below to account for iPhone 6 and 6 plus screen sizesSardonic
S
28

We now need to account for iPhone 6 and 6Plus screen sizes. Here's an updated answer

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
}

Some useful info

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"
Sardonic answered 24/9, 2014 at 13:7 Comment(5)
it is just doesn't work for me iPhone 5 decided as 4 iPhone 6+ didn't decide at all Oh I got it I am in landscape I should change height with width :)Quicken
if your app is in landscape mode then make sure you change result.height to result.widthSardonic
hmm .. on iPhone 4 (iOS 6.0) it didn't swap :( could be iOS 6.0 prob or an iPhone 4 ?Quicken
Okay I checked the view swapped only in iOS 8 and greaterQuicken
iPhone 6 giving height = 568Segment
F
15

I've taken the liberty to put the macro by Macmade into a C function, and name it properly because it detects widescreen availability and NOT necessarily the iPhone 5.

The macro also doesn't detect running on an iPhone 5 in case where the project doesn't include the [email protected]. Without the new Default image, the iPhone 5 will report a regular 480x320 screen size (in points). So the check isn't just for widescreen availability but for widescreen mode being enabled as well.

BOOL isWidescreenEnabled()
{
    return (BOOL)(fabs((double)[UIScreen mainScreen].bounds.size.height - 
                                               (double)568) < DBL_EPSILON);
}
Fugleman answered 21/9, 2012 at 14:0 Comment(5)
I still prefer the macros, for performance reasons. Please see the edit to my answer. It also checks the model.Erminois
You're also right saying an iPhone 5 will report a regular 480x320 screen size, without the new default image. But I think there is no point detecting an iPhone 5 in a non-optimised app. : )Erminois
@Erminois Indeed, there is no point, but it's good to keep in mind in case detection doesn't work. Also, functions can be inlined. They'll also be inlined where compiler's optimizer thinks it's a good idea and where it can know it's permissible (e.g. function is in the same module). Implementing stuff like this through a function may sometimes bring additional type checking.Eucharis
The performance related question is, why would you run this check thousands of times during your render loop? Otherwise, performance is a non-issue and clarity and avoiding side-effects of greater importance.Fugleman
I gave you a +1 for this because I like the separate function rather than a macro, but I have to point out that it's not really correct or complete. To detect widescreen, don't look at the height of the screen. Instead, look at the aspect ratio and return true only if the aspect ratio is greater than or equal to 16:9.Kinson
I
11

Here is our codes, test passed on ios7/ios8 for iphone4,iphone5,ipad,iphone6,iphone6p, no matter on devices or simulator:

#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 )
Interpretative answered 7/10, 2014 at 7:18 Comment(1)
I'm testing on an iPhone 6P and my if statement is falling into the IS_IPHONE_5 condition? How can this be, you're code looks good? I did a straight copy and paste with a simple if/else and I know my phone is a 6 plus running iOS 8.3.Bradfordbradlee
H
7

I used hfossli's answer and translated it to 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)
Higher answered 5/1, 2015 at 21:20 Comment(0)
C
6

this is the macro for my cocos2d project. should be the same for other apps.

#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))
Chance answered 29/9, 2012 at 4:32 Comment(0)
S
5
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
    // This is iPhone 5 screen
} else {
    // This is iPhone 4 screen
}
Stringboard answered 12/9, 2013 at 12:3 Comment(0)
R
3

In Swift, iOS 8+ project I like to make an extension on UIScreen, like:

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

}

(NOTE: nativeBounds is in pixels).

And then the code will be like:

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

So the code makes it clear that this is a check for the main screen, not for the device model.

Rattlebrained answered 22/5, 2016 at 15:37 Comment(0)
F
2

Borrowing from Samrat Mazumdar's answer, here's a short method that estimates the device screen size. It works with the latest devices, but may fail on future ones (as all methods of guessing might). It will also get confused if the device is being mirrored (returns the device's screen size, not the mirrored screen size)

#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
    }
} 
Frescobaldi answered 10/10, 2012 at 23:25 Comment(3)
Needs revision for iPad mini which, I don't believe you'll be able to determine in this manor.Irradiate
Yeah, iPad mini has the same resolution as the iPad2, so this method doesn't work for that. Not sure how to handle that case right now...Frescobaldi
You're not supposed to. You can check the device identifier for "iPad 2,5" buy also you need to check for 2,6 and 2,7 - the wifi only version, gsm and CDMA. But that means that the next iPad mini will be released and you'll need to update to hard code to those identifiers too which you can't know before hand. You can't continently know when you're on an iPad mini because really you shouldn't try to "optimise" for the smaller screenIrradiate
T
2

I think it should be good if this macro will work in device and simulator, below are the solution.

#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)
Tellurian answered 8/2, 2013 at 10:38 Comment(0)
G
2

I found that answers do not include a special case for Simulators.

#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 )
Gunlock answered 7/11, 2013 at 21:39 Comment(0)
S
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;

}
Slavism answered 19/5, 2014 at 14:41 Comment(1)
iPhone5 = FALSE; is unnecessary because the variable has already that value if it's not changedWinterwinterbottom
T
2

This has been answered a hundred times but this solution worked the best for me and helped address the issue when new devices are introduced and I don't have a size defined.

Swift 5 Helper:

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

This is because it's easy to memorize a phone's inch sizes, like, "5.5 inch" or "4.7 inch" device but difficult to remember the exact pixel sizes.

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

This also gives you the opportunity to do something like this:

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

The default: tries to uses the screen size and scale to try and calculate the diagonal inches. This is in case some new device size appears, it will try its best to determine and code, such as the last example, should still work.

Tetramethyldiarsine answered 3/11, 2016 at 3:6 Comment(0)
L
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

     }
Leitmotif answered 11/12, 2012 at 5:39 Comment(0)
B
1

Relying in the size is wrong in so many levels. How about we ask to the system?

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

Taken from Best way to detect hardware type, iPhone4 or iPhone5?, edzio27 answer.

Bubalo answered 28/2, 2013 at 23:3 Comment(0)
D
1

This way you can detect device family.

    #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
Digitoxin answered 10/4, 2014 at 7:17 Comment(0)
G
1

If the project is created using Xcode 6, then use the below mentioned code to detect the devices..

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");
}

If the project was created in Xcode 5 and opened in Xcode 6, then use the below mentioned code to detect the devices.(This code works if no launching images for iPhone 6,6+ are assigned)

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

If you are still using Xcode 5 all together then use the following code to detect the devices (iPhone 6 and 6+ will not be detected)

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");

}
Granjon answered 28/9, 2014 at 17:24 Comment(0)
S
1
  1. Add a 'New Swift File'-> AppDelegateEx.swift

  2. add an extension to 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. usage:

        if AppDelegate.isIPhone5() {
            collectionViewTopConstraint.constant = 2
        }else if AppDelegate.isIPhone6() {
            collectionViewTopConstraint.constant = 20
        }
    
Shaff answered 27/10, 2015 at 2:13 Comment(0)
D
1

In Swift 3 you can use my simple class KRDeviceType.

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

It well documented and supports operators ==, >=, <=.

For example to detect if device has bounds of iPhone 6/6s/7, you can just use next comparison:

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

To detect if device has bounds of iPhone 5/5S/SE or earlier (iPhone 4s) you can use next comparison:

if KRDeviceType() <= .iPhone5 {   //iPhone 5/5s/SE of iPhone 4s
// Perform appropiate operations (for example, set up constraints for those old devices)
}
Ductile answered 9/4, 2017 at 9:48 Comment(0)
J
0

use the following Code:

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
}
Jevon answered 10/10, 2012 at 7:18 Comment(0)
S
0

Here is the correct test of the device, without depending on the orientation

- (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;
}
Snooker answered 13/4, 2016 at 12:58 Comment(0)
O
-2

Used to detect iPhone and iPad Devices of all 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) 
Ophiolatry answered 24/9, 2014 at 14:58 Comment(6)
iPhone 6 has no retina display?Provoke
iPhone6 has the ratina(@2X) display. and iPhone6 plus has the HD(@3X) display.Ophiolatry
So if tested for IS_RETINA on an iPhone 6 plus, 1x code is executed?Provoke
See This Link. #25757089Ophiolatry
you don't get it: your rules will yield @1x, where it should yield @3x. anyway: as you are simply copy&pasting: -1Provoke
@VaibhavSharma I mistakenly edited your post. I removed one line. Sorry. I don't know how to roll back.Anemology

© 2022 - 2024 — McMap. All rights reserved.