7

One of my apps connects to a web app service that delivers device specific news to to the user. To adapt this to the latest iPhone versions I need to programmatically distinguish between the iPhone XS and iPhone X. How can this be done?

[[UIScreen mainScreen] bounds].size was always a good starting point to tell the different devices apart. However, iPhone XS and iPhone X have the same screen dimensions: 1125 x 2436. Thus using [[UIScreen mainScreen] bounds].size does not work in this case.

Is there any other method to detect the latest iPhone versions?

EDIT: This is NOT a duplicate of the question "How to detected iPhone X" since all answers/solutions discussed there use the screen dimensions to specify the device type. As described above iPhone X and iPhone XS have the exact same dimensions and thus the solutions cannot tell these two apart...

Cœur
  • 37,241
  • 25
  • 195
  • 267
Andrei Herford
  • 17,570
  • 19
  • 91
  • 225
  • Usually, you prefer use UIDevice: https://stackoverflow.com/questions/26028918/how-to-determine-the-current-iphone-device-model, no? But I don't know what's the returned value yet. – Larme Sep 13 '18 at 14:47
  • Many answers from the linked duplicate question will help you distinguishing **any** device. – Cœur Sep 27 '18 at 16:53
  • take a look https://stackoverflow.com/a/52821290/3472073 – ale_stro Nov 12 '18 at 13:01

3 Answers3

22

You can determine using UIScreen.main.nativeBounds.

 if UIDevice().userInterfaceIdiom == .phone {
        switch UIScreen.main.nativeBounds.height {
        case 1136:
            print("IPHONE 5,5S,5C")
        case 1334:
            print("IPHONE 6,7,8 IPHONE 6S,7S,8S ")
        case 1920, 2208:
            print("IPHONE 6PLUS, 6SPLUS, 7PLUS, 8PLUS")
        case 2436:
            print("IPHONE X, IPHONE XS, IPHONE 11 PRO")
        case 2688:
            print("IPHONE XS MAX, IPHONE 11 PRO MAX")
        case 1792:
            print("IPHONE XR, IPHONE 11")
        default:
            print("UNDETERMINED")
        }
    }

.nativeBounds won't change even if the orientation is changed. https://developer.apple.com/documentation/uikit/uiscreen/1617810-nativebounds

Umair
  • 1,203
  • 13
  • 15
10

I use DeviceUtil to determine an iOS device's model.

According to this DeviceUtil GitHub post, the returned UIDevice hardwareString values are:

iPhone11,2 = iPhone XS
iPhone11,4 = iPhone XS Max
iPhone11,8 = iPhone XR

Curiously, the Xcode 10 GM Simulator's [UIScreen mainScreen].bounds.size returns 375 x 812 for iPhone X, XS, XS Max, and R devices. I had expected 414 x 896 for the XS Max and XR.

lifjoy
  • 2,158
  • 21
  • 19
  • I found that the Simulator reported these sizes because my app targets iOS 10 or later. To enable full screen resolution, my app must target iOS 11 or later. – lifjoy Sep 13 '18 at 20:06
  • Your app must target iOS 10 or later AND, must use launch screen file instead launch image source. – cmii Sep 18 '18 at 16:37
  • 1
    You are correct about the launch image. But I think iOS 11 is also needed. On developer.apple.com/iphone, there's a paragraph that says "Your app will run in Full Screen Display Mode on iPhone X, iPhone XS, iPhone XS Max, and iPhone XR if your project’s base SDK is set to iOS 11 or later and you have a Launch Storyboard or iPhone X launch image". My app targets iOS 10 AND does have the proper XS Max launch image, but its still scaled on the XS Max. – lifjoy Sep 18 '18 at 20:03
  • I'm working with last Xcode, iOS 10 target, with full screen presentation ON, and [UIScreen mainScreen].bounds.size returns the correct size for all devices. – cmii Sep 19 '18 at 12:21
  • Thanks, @cmii. You are so right. Turns out that I botched the new UILaunchImages dictionary that I added to support {414, 896}, LaunchImage-iPhone6_5-Port. Simulator is now returning the expected screen sizes. – lifjoy Sep 19 '18 at 18:05
3

#import <sys/utsname.h> // import it in your header or implementation file.

+(NSString*)deviceName
{
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *machineName = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];


    NSDictionary *commonNamesDictionary =
    @{
      @"i386":     @"i386 Simulator",
      @"x86_64":   @"x86_64 Simulator",

      @"iPhone1,1":    @"iPhone",
      @"iPhone1,2":    @"iPhone 3G",
      @"iPhone2,1":    @"iPhone 3GS",
      @"iPhone3,1":    @"iPhone 4",
      @"iPhone3,2":    @"iPhone 4",
      @"iPhone3,3":    @"iPhone 4",
      @"iPhone4,1":    @"iPhone 4S",
      @"iPhone5,1":    @"iPhone 5",
      @"iPhone5,2":    @"iPhone 5",
      @"iPhone5,3":    @"iPhone 5c",
      @"iPhone5,4":    @"iPhone 5c",
      @"iPhone6,1":    @"iPhone 5s",
      @"iPhone6,2":    @"iPhone 5s",

      @"iPhone7,1":    @"iPhone 6+",
      @"iPhone7,2":    @"iPhone 6",

      @"iPhone8,1":    @"iPhone 6S",
      @"iPhone8,2":    @"iPhone 6S+",
      @"iPhone8,4":    @"iPhone SE",
      @"iPhone9,1":    @"iPhone 7",
      @"iPhone9,2":    @"iPhone 7+",
      @"iPhone9,3":    @"iPhone 7",
      @"iPhone9,4":    @"iPhone 7+",
      @"iPhone10,1":    @"iPhone 8",
      @"iPhone10,2":    @"iPhone 8+",

      @"iPhone10,3":    @"iPhone X",
      @"iPhone11,2":    @"iPhone XS",
      @"iPhone11,4":    @"iPhone XS Max",
      @"iPhone11,8":    @"iPhone XR",

      @"iPad1,1":  @"iPad",
      @"iPad2,1":  @"iPad 2",
      @"iPad2,2":  @"iPad 2",
      @"iPad2,3":  @"iPad 2",
      @"iPad2,4":  @"iPad 2",
      @"iPad2,5":  @"iPad Mini 1G",
      @"iPad2,6":  @"iPad Mini 1G",
      @"iPad2,7":  @"iPad Mini 1G",
      @"iPad3,1":  @"iPad 3",
      @"iPad3,2":  @"iPad 3",
      @"iPad3,3":  @"iPad 3",
      @"iPad3,4":  @"iPad 4",
      @"iPad3,5":  @"iPad 4",
      @"iPad3,6":  @"iPad 4",

      @"iPad4,1":  @"iPad Air",
      @"iPad4,2":  @"iPad Air",
      @"iPad4,3":  @"iPad Air",

      @"iPad5,3":  @"iPad Air 2",
      @"iPad5,4":  @"iPad Air 2",

      @"iPad4,4":  @"iPad Mini 2G",
      @"iPad4,5":  @"iPad Mini 2G",
      @"iPad4,6":  @"iPad Mini 2G",

      @"iPad4,7":  @"iPad Mini 3G",
      @"iPad4,8":  @"iPad Mini 3G",
      @"iPad4,9":  @"iPad Mini 3G",

      @"iPod1,1":  @"iPod 1st Gen",
      @"iPod2,1":  @"iPod 2nd Gen",
      @"iPod3,1":  @"iPod 3rd Gen",
      @"iPod4,1":  @"iPod 4th Gen",
      @"iPod5,1":  @"iPod 5th Gen",
      @"iPod7,1":  @"iPod 6th Gen",
      };

    NSString *deviceName = commonNamesDictionary[machineName];

    if (deviceName == nil) {
        deviceName = machineName;
    }

    return deviceName;
}

It will return device model for you ,also included XS, XR, XS Max

    #define IS_IPHONE        (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    #define IS_IPHONE_4      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 480.0)
    #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_6PLUS  (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)
    #define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
    #define IS_IPHONE_X      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
#define IS_IPHONE_X      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)

    #define IS_IPHONE_XS      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 812.0)
    #define IS_IPHONE_X_MAX      (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 896.0)
    #define IS_RETINA        ([[UIScreen mainScreen] scale] >= 2.0) // 3.0 for iPhone X, 2.0 for others

    #define IS_IPAD_DEVICE   [(NSString*)[UIDevice currentDevice].model hasPrefix:@"iPad"]

Note:- Be careful, it works fine only for portrait orientation

Jagveer Singh
  • 2,258
  • 19
  • 34