snaggs
snaggs

Reputation: 5713

iOS devices return different format device model, why?

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

Upvotes: 6

Views: 1049

Answers (3)

Andy Darwin
Andy Darwin

Reputation: 478

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

Upvotes: 0

Nirav Kotecha
Nirav Kotecha

Reputation: 2581

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

Upvotes: 2

Sergey Grishchev
Sergey Grishchev

Reputation: 12051

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.

Upvotes: 2

Related Questions