6

I use this method to fetch device model name:

+ (NSString *) machineModel
{
    const char *name = "hw.model";
#if TARGET_OS_IPHONE
    // .model on iOS returns internal model name (e.g. "N51AP") when we'd prefer to see the model identifier here ("iPhone6,1")
    name = "hw.machine";
#endif

    int error = 0;
    size_t length = 0;
    error = sysctlbyname(name, NULL, &length, NULL, 0);

    if (error != 0) {
        return nil;
    }

    char *p = malloc(sizeof(char) * length);
    if (p) {
        error = sysctlbyname(name, p, &length, NULL, 0);
    }

    if (error != 0) {
        free(p);
        return nil;
    }

    NSString *machinemodel = [NSString stringWithFormat:@"%s", p];        
    free(p);        
    return machinemodel;
}

However, when I run this code on thousands of devices I get following options in my database:

"iPhone7;1"
"iPhone8,1"
"iPhone7;2"
"iPhone"
"iPhone9;3"
"iPhone7;1"
"iPhone8,1"
"iPhone8,1"
"iPhone7,2"
"iPhone7;2"
"iPhone9;1"
"iPhone7;2"
...

Problem

Sometimes I have , separator, sometimes ; and sometimes I see no number: "iPhone"

Why does it happen?


I would expect this from Android devices (5K different manufactories) but why iOS where only Apple is owner

snaggs
  • 5,543
  • 17
  • 64
  • 127
  • That's Apple for you. You can't rely on model name for your code really. Maybe you can explain what your intention is, then maybe we can help to give ideas how to accomplish it without using model names. – GeneCode Aug 28 '17 at 00:15
  • @GeneCode Well, I expect same behavior from Android devices, different brands, manufacture and so on. But why in iOS :). Generally like crashlytics does today, I want to show to user in his dashboard model ratio percentage. And because I have `iPhone7;2`, `iPhone7,2` and `iPhone` unknown, I need to do additional work on server side. – snaggs Aug 28 '17 at 03:55
  • 1
    Do you have access to any of the devices with `;` in their name? Is there something specific about them? E.g. jailbreak or beta iOS installed? – Sulthan Aug 29 '17 at 09:42
  • Check this https://stackoverflow.com/questions/26028918/ios-how-to-determine-the-current-iphone-device-model-in-swift it may help you . – Prabakaran Aug 29 '17 at 10:24
  • 1
    I am suspecting either a difference in versions (OS or revision), so it would be handy if you could output that alongside the model to verify. Also would try using 'stringWithUTF8String' instead to help rule out any encoding issues. – kvr Sep 05 '17 at 04:24

3 Answers3

2

I believe you have an issue with the code, by accessing the model name directly. Probably on some iOS versions or iOS architectures it works differently.

I suggest you use some higher level library like DeviceKit or Device - it works super well for me and always gives correct results.

If you don't want to use them directly, at least you can see how they work under the hood and implement the same logic yourself.

Sergey Grischyov
  • 11,995
  • 20
  • 81
  • 120
2

@snaggs you can add this method it will give you proper output. i have call your method in first line of method.

- (NSString *)platformString
{
    NSString *platform = [self machineModel];
    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 (GSM)";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"iPhone 4 (CDMA)";
    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:@"iPhone7,1"])    return @"iPhone 6 GSM";
    if ([platform isEqualToString:@"iPhone7,2"])    return @"iPhone 6 GSM+CDMA";
    if ([platform isEqualToString:@"iPhone8,1"])    return @"iPhone 6+ GSM";
    if ([platform isEqualToString:@"iPhone8,2"])    return @"iPhone 6+ Global";
    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 (GSM)";
    if ([platform isEqualToString:@"iPad4,4"])      return @"iPad Mini Retina (WiFi)";
    if ([platform isEqualToString:@"iPad4,5"])      return @"iPad Mini Retina (GSM)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";
    if ([platform isEqualToString:@"x86_64"])       return @"Simulator";
    return platform;
}
Nirav Kotecha
  • 2,493
  • 1
  • 12
  • 26
0

With this knowledge, we can finally get a “Hardware model” value by using sysctl to get the HW_MODEL for OS X and HW_MACHINE for iOS systems.

In iOS, you should use hw.machinerather than hw.model

size_t size;
int nR = sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = (char *)malloc(size);
nR = sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *deviceString = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);

More info

Andy Darwin
  • 478
  • 5
  • 19