Detecting iPhone 6/6+ screen sizes in point values

IosIphoneIos8

Ios Problem Overview


Given the newly announced iPhone 6 screen sizes:

iPhone 6: 1334h * 750w @2x (in points: 667h * 375w)
iPhone 6+: 1920 * 1080 @3x (in points: 640h * 360w)

I was wondering if there is code that allows me to detect which screen size the user's device is, so that I could adjust and size UIImages and other materials accordingly with the user's device.

So far, I have been using the following:

- (NSString *) platform{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    return platform;
}

- (NSString *) platformString{
    NSString *platform = [self platform];
    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"Verizon iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone5,3"])    return @"iPhone 5c (GSM)";
    if ([platform isEqualToString:@"iPhone5,4"])    return @"iPhone 5c (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone6,1"])    return @"iPhone 5s (GSM)";
    if ([platform isEqualToString:@"iPhone6,2"])    return @"iPhone 5s (GSM+CDMA)";
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"])      return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([platform isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([platform isEqualToString:@"iPad2,7"])      return @"iPad Mini (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([platform isEqualToString:@"iPad3,2"])      return @"iPad 3 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,3"])      return @"iPad 3 (GSM)";
    if ([platform isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([platform isEqualToString:@"iPad3,5"])      return @"iPad 4 (GSM)";
    if ([platform isEqualToString:@"iPad3,6"])      return @"iPad 4 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad4,1"])      return @"iPad Air (WiFi)";
    if ([platform isEqualToString:@"iPad4,2"])      return @"iPad Air (Cellular)";
    if ([platform isEqualToString:@"iPad4,4"])      return @"iPad mini 2G (WiFi)";
    if ([platform isEqualToString:@"iPad4,5"])      return @"iPad mini 2G (Cellular)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";
    if ([platform isEqualToString:@"x86_64"])       return @"Simulator";
    return platform;
}

As such, should I assume iPhone7,1 and iPhone7,2 are the iPhone 6 while iPhone7,3 and iPhone7.4 are the pluses? If anyone has more concrete way to tell it'd be great, thanks.!

Ios Solutions


Solution 1 - Ios

The first screen will be the device screen, Note that a launch images for the new phones have to be added before, otherwise the app is running in Zoomed Mode for older apps : Here is the code I used to check this out. Note: This only works with version iOS 8 and higher:

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
          NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

Code for detecting iPhone 6 Plus:

#define IS_PAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_PHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)

-(BOOL)iPhone6PlusDevice{
    if (!IS_PHONE) return NO;
    if ([UIScreen mainScreen].scale > 2.9) return YES;   // Scale is only 3 when not in scaled mode for iPhone 6 Plus
    return NO;
}

or

-(BOOL) iPhone6PlusUnZoomed{
    if ([self iPhone6PlusDevice]){
        if ([UIScreen mainScreen].bounds.size.height > 720.0) return YES;  // Height is 736, but 667 when zoomed.
    }
    return NO;
}

Note: If you are checking for iPhone 6 Plus, to adjust the user interface then don´t rely on .nativeScale, because the simulator and actual device give different results. Due to the comment below. Scale is a CGFloat and thus, code should not check equality, because some floats values may never be equal.


After adding Launch Screen you can utilise the new iPhone sizes, otherwise your app will still look scaled.

Updated for the new iPhones 11, 11 Pro and 11 Pro Max

Size for iPhone 11 Pro Max with @3x scaling, coordinate space: 414 x 896 points and 1242 x 2688 pixels, 458 ppi, device physical size is 3.06 x 6.22 in or 77.8 x 158.0 mm. 6.5" Super Retina XDR display.

Size for iPhone 11 Pro with @3x scaling, coordinate space: 375 x 812 points and 1125 x 2436 pixels, 458 ppi, device physical size is 2.81 x 5.67 in or 71.4 x 144.0 mm. 5.8" Super Retina XDR display.

Size for iPhone 11 with @2x scaling, coordinate space: 414 x 896 points and 828 x 1792 pixels, 326 ppi, device physical size is 2.98 x 5.94 in or 75.7 x 150.9 mm. 6.1" Liquid Retina HD display.

Size for iPhone X Max with @3x scaling (Apple name: Super Retina HD 6.5 display"), coordinate space: 414 x 896 points and 1242 x 2688 pixels, 458 ppi, device physical size is 3.05 x 6.20 in or 77.4 x 157.5 mm.

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X🅂 Max Screen bounds: (0.0, 0.0, 414.0, 896.0), Screen resolution: (0.0, 0.0, 1242.0, 2688.0), scale: 3.0

Size for iPhone X with @2x scaling (Apple name: Super Retina HD 6.1" display), coordinate space: 414 x 896 points and 828 x 1792 pixels, 326 ppi, device physical size is 2.98 x 5.94 in or 75.7 x 150.9 mm.

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X🅁 Screen bounds: (0.0, 0.0, 414.0, 896.0), Screen resolution: (0.0, 0.0, 828.0, 1792.0), scale: 2.0

Size for iPhone X and iPhone X with @3x scaling (Apple name: Super Retina HD 5.8" display), coordinate space: 375 x 812 points and 1125 x 2436 pixels, 458 ppi, device physical size is 2.79 x 5.65 in or 70.9 x 143.6 mm.

let screen = UIScreen.main
print("Screen bounds: \(screen.bounds), Screen resolution: \(screen.nativeBounds), scale: \(screen.scale)")
//iPhone X🅂 and X Screen bounds: (0.0, 0.0, 375.0, 812.0), Screen resolution: (0.0, 0.0, 1125.0, 2436.0), scale: 3.0

Size for iPhone 8, 7, 6 Plus and iPhone 8, 7, 6S Plus with @3x scaling (Apple name: Retina HD 5.5), Coordinate space: 414 x 736 points and 1242 x 2208 pixels, 401 ppi, screen physical size is 2.7 x 4.8 in or 68 x 122 mm:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

Size for iPhone 6 and iPhone 6S with @2x scaling (Apple name: Retina HD 4.7), Coordinate space: 375 x 667 points and 750 x 1334 pixels, 326 ppi, screen physical size is 2.3 x 4.1 in or 58 x 104 mm:

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

And iPhone 5 for comparison is 640 x 1136, iPhone 4 640 x 960.

Note: Upload LaunchImages otherwise the app will run scaled and not show correct scaling, or screen sizes.

Comparing iPhone 6 and 6 Plus

Solution 2 - Ios

If you prefer macros here are the ones, that you can use to differentiate between the iPhone models. These are based on the point values.

#define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)480) < DBL_EPSILON)
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)

Solution 3 - Ios

I use the following code to determine what device is running (it's a little bit quick and dirty but it does the trick)

if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){
	
	CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
	CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
	if( screenHeight < screenWidth ){
		screenHeight = screenWidth;
	}
	
	if( screenHeight > 480 && screenHeight < 667 ){
		NSLog(@"iPhone 5/5s");
	} else if ( screenHeight > 480 && screenHeight < 736 ){
		NSLog(@"iPhone 6");
	} else if ( screenHeight > 480 ){
		NSLog(@"iPhone 6 Plus");
	} else {
		NSLog(@"iPhone 4/4s");
	}
}

(This only works when iPhone 6 / 6 Plus is enabled by adding the appropriate splash screens)

Solution 4 - Ios

On the physical device, iPhone 6 Plus's main screen's bounds is 2208x1242 and nativeBounds is 1920x1080. There is hardware scaling involved to resize to the physical display.

On the simulator, the iPhone 6 Plus's main screen's bounds and nativeBounds are both 2208x1242.

In other words... Videos, OpenGL, and other things based on CALayers that deal with pixels will deal with the real 1920x1080 framebuffer on device (or 2208x1242 on sim). Things dealing with points in UIKit will be deal with the 2208x1242 (x3) bounds and get scaled as appropriate on device.

The simulator does not have access to the same hardware that is doing the scaling on device and there's no really much of a benefit to simulating it in software as they'd produce different results than the hardware. Thus it makes sense to set the nativeBounds of a simulated device's main screen to the bounds of the physical device's main screen.

iOS 8 added API to UIScreen (nativeScale and nativeBounds) to let a developer determine the resolution of the CADisplay corresponding to the UIScreen.

Solution 5 - Ios

You can detect iPhone 6 Plus based on its native scale, using this macro:

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)

Solution 6 - Ios

Check the updated list on wiki , there I got 7,2 for iPhone 6 and 7,1 for iPhone 6 plus.

Solution 7 - Ios

Hannes Sverrisson's answer is almost correct. The iPhone 6 coordinate system is in fact larger than the 5s Using his code:

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
      NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

The coordinate system for apps providing the correct launch images are:

Size for iPhone 6 (Retina HD 4.7) with @2x scaling, Coordinate space: 375 x 667 and 750 x 1334 actual points:

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

Size for iPhone 6 Plus (Retina HD 5.5) with @3x scaling, Coordinate space: 414 x 736 and 1242 x 2208 actual points:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

Solution 8 - Ios

This is what I use in my app with iOS 8:

window=[[[UIApplication sharedApplication] windows] firstObject];

NSLog(@"screenHeight=%f width=%f",window.frame.size.height,window.frame.size.width);

if (window.frame.size.height == 480) {
        
        do stuff here... 
    }

Prior to Xcode6 / iOS 8, I used this, but screen bounds does not work properly with the resizable simulator or at least it didn't in the Xcode6 betas...

CGRect screenBounds=[[UIScreen mainScreen] bounds];

if (screenBounds.size.height >= 568) {

do stuff here...

}
    

Solution 9 - Ios

All three devices have (pretty much) the same number of points per inch. So your images will automatically be the same physical size.

Use [[UIScreen mainScreen] bounds] to get the total number of points on the screen. Divide by 163 to get the approximate size in inches if you really want it.

Notice that the 6+ does not return 1080p because it doesn't render to a 1080p buffer. It renders such that output is approximately 160 points per inch, using @3x assets.

No need to second guess.

E.g. if you write this code:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 163, 163)];
view.backgroundColor = [UIColor redColor];
[self.view addSubview:view];

You'll get a view that is pretty much the same physical size — one inch square — on all iOS devices.

Apple has already done the hard work, so you don't have to.

Solution 10 - Ios

I had to detect the iPhone 6 Plus in an app built with iOS 7. Because nativeScale isn't available on [UIScreen mainScreen] I tried to use [UIScreen mainScreen] scale] but this just returned 2.0. So I came up with this solution to detect the iPhone 6 Plus on iOS 7 (should also work on iOS 8):

-(BOOL)iPhone6Plus{
BOOL isiPhone6Plus = NO;
SEL selector = NSSelectorFromString(@"scale");
if ([[UIScreen mainScreen] respondsToSelector:selector]) {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:[UIScreen mainScreen]];
    [invocation invoke];
    float returnValue;
    [invocation getReturnValue:&returnValue];
    if (returnValue == 3.0) {
        isiPhone6Plus = YES;
    }
    NSLog(@"ScaleFactor %1.2f", returnValue);
}
return isiPhone6Plus;

}

The interesting part of this code is, that if I use NSInvocation the return value of the scale selector will be 3.0. Calling this method directly on iOS 7 returns 2.0.

Solution 11 - Ios

to me this works for me

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
    UIStoryboard *storyBoard;
    
    CGSize result = [[UIScreen mainScreen] bounds].size;
    CGFloat scale = [UIScreen mainScreen].scale;
    result = CGSizeMake(result.width * scale, result.height * scale);
    
    if(result.height == 1136){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_5" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];
    
    } else if(result.height == 1334){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];
    
    } else if(result.height == 2208){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6_plus" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];
    
    } else if(result.height == 960){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_4" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];
        
    }

} else {
    
    UIStoryboard *storyBoard;
    
    storyBoard = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil];
    UIViewController *initViewController = [storyBoard instantiateInitialViewController];
    [self.window setRootViewController:initViewController];
    
}

Solution 12 - Ios

Here is the updated source code you are using this.

iPhone 6 and iPhone 6 Plus models have been added.

Solution 13 - Ios

An interesting thing to remember when reading screen sizes on my iPhone 6 Plus was that when you have it set to "Zoomed" mode it will show up as a the iPhone 6 height (667) and when you have it set to "Standard" it will show up as (736). Shouldn't really matter, but if you specifically wanted to know the device type for some reason ( Maybe Reporting ), this could fool you.

See this.

Solution 14 - Ios

One major thing that the above answers are leaving out is the fact that in iOS7 and below, when you check [[UIScreen mainScreen] bounds] for the screen bounds, it always lists the width and height as the same no matter what orientation the phone is in. So if it's an iPhone5 in landscape mode, it will still list the width as 320 and height as 568. In iOS8, this changed, now if that same iPhone5 is in landscape, it will list the width as 568 and the height as 320. Below are methods which account for this:

+ (BOOL) deviceHasFourInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:568.0];
}

+ (BOOL) deviceHasFourPointSevenInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:667.0];
}

+ (BOOL) deviceHasFivePointFiveInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:3.0 height:736.0];
}

+ (BOOL) deviceHasScreenWithIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom scale:(CGFloat)scale height:(CGFloat)height
{
    CGRect mainScreenBounds = [[UIScreen mainScreen] bounds];
    CGFloat mainScreenHeight;
    
    if ([OperatingSystemVersion operatingSystemVersionLessThan:@"8.0"])
    {
        mainScreenHeight = mainScreenBounds.size.height;
    }
    else
    {
        mainScreenHeight = (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ? mainScreenBounds.size.width : mainScreenBounds.size.height;
    }
    
    if ([[UIDevice currentDevice] userInterfaceIdiom] == userInterfaceIdiom && [[UIScreen mainScreen] scale] == scale && mainScreenHeight == height)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

Also here are the accompanying OperatingSystem class methods:

+ (NSString *) currentOperatingSystemVersion
{
    return [[UIDevice currentDevice] systemVersion];
}
+ (BOOL) operatingSystemVersionLessThanOrEqualTo:(NSString *) operatingSystemVersionToCompare
{
    return ([[self currentOperatingSystemVersion] compare: operatingSystemVersionToCompare options:NSNumericSearch] != NSOrderedDescending);    
}

Solution 15 - Ios

this is guaranteed to compile in xcode 5 (xocde 6 at this point is still flaky, and you can't submit an ipa to itunes connect for app store approval using beta software, which xcode 6 is right now)

the thing is xcode 5 won't recognize the nativeScale selector.. this is how you can do it in run time:

+ (BOOL)isIphone6Plus
{
    SEL selector = NSSelectorFromString(@"nativeScale");
    if ([[UIScreen mainScreen] respondsToSelector:selector]) {
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                        [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIScreen mainScreen]];
            [invocation invoke];
            float returnValue;
            [invocation getReturnValue:&returnValue];
            NSLog(@"::: this is native scale %f", returnValue);
            return (returnValue == 3.0f);
    } else {
        // iphone 6 plus come prepackaged with iOS8.. 
        // so if the phone doesn't know what nativeScale means
        // it's not an iphone6plus phone
        return NO;
    }
}

Solution 16 - Ios

Swift 4

let kSize = UIScreen.main.bounds.size //kSize is screen CGSize

if(kSize.width == 320){
             //iphone se
}else if(kSize.width == 375 && kSize.height == 667){
             //iphone 7 / 8
}else if(kSize.width == 375){
            //iphone x
}else if(kSize.width == 414){
           //iphone 7 plus/ 8 plus
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondaspianistView Question on Stackoverflow
Solution 1 - IosSverrissonView Answer on Stackoverflow
Solution 2 - IosbkhayllView Answer on Stackoverflow
Solution 3 - IosRoland KeesomView Answer on Stackoverflow
Solution 4 - IosJeremy Huddleston SequoiaView Answer on Stackoverflow
Solution 5 - Iossweepy_View Answer on Stackoverflow
Solution 6 - Iosares777View Answer on Stackoverflow
Solution 7 - IosPaul BuchananView Answer on Stackoverflow
Solution 8 - IosDavid LView Answer on Stackoverflow
Solution 9 - IosTommyView Answer on Stackoverflow
Solution 10 - IosSvenView Answer on Stackoverflow
Solution 11 - Iososcar castellonView Answer on Stackoverflow
Solution 12 - IosSergey FilippovView Answer on Stackoverflow
Solution 13 - IosShippyView Answer on Stackoverflow
Solution 14 - IosSer PounceView Answer on Stackoverflow
Solution 15 - IosabboodView Answer on Stackoverflow
Solution 16 - IosKishore KumarView Answer on Stackoverflow