Determine iPhone and iPad Hardware Machine and Device Type

Using the UIDevice class, you can figure out if your application is running on a iPod or an iPhone. To get this information, access the property named model which will return an NSString of iPhone or iPod touch. However, there may be times when you need more specifics, for example is the iPhone the latest device, a 3GS or on the flip side, is the iPod a first or second generation device?

Accessing the system hardware will reveal the information we need to make the above distinctions. We’ll use a category to extend the UIDevice class with a method that returns the “machine” type as a string. Begin with the interface definition below:

@interface UIDevice(machine)
- (NSString *)machine;
@end

To access the hardware type we’ll call a function in the standard C library:

sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);

The first parameter is the name of the system information we are after. The information will be copied into the buffer ‘oldp’ and we specify the size of this buffer in the ‘oldlenp’ parameter. We set ‘newp’ to NULL as this is for setting a value (versus getting a value). On a similar note, we set ‘newlen’ to 0, as that is reserved for calls to set information.

Putting all that together into, the implementation of our class looks as follows:

#import "UIDevice+machine.h"
#include <sys/types.h>
#include <sys/sysctl.h>
 
@implementation UIDevice(machine)
 
- (NSString *)machine
{
  size_t size;
 
  // Set 'oldp' parameter to NULL to get the size of the data
  // returned so we can allocate appropriate amount of space
  sysctlbyname("hw.machine", NULL, &size, NULL, 0); 
 
  // Allocate the space to store name
  char *name = malloc(size);
 
  // Get the platform name
  sysctlbyname("hw.machine", name, &size, NULL, 0);
 
  // Place name into a string
  NSString *machine = [NSString stringWithCString:name];
 
  // Done with this
  free(name);
 
  return machine;
}
 
@end

We can now call the new method as follows:

#import "UIDevice+machine.h"
 
...
 
NSLog(@"device: %@", [[UIDevice currentDevice] machine]);

The return values will be as follows:

  • iPhone Simulator == i386
  • iPhone == iPhone1,1
  • 3G iPhone == iPhone1,2
  • 3GS iPhone == iPhone2,1
  • 4 iPhone == iPhone3,1
  • 1st Gen iPod == iPod1,1
  • 2nd Gen iPod == iPod2,1
  • 3rd Gen iPod == iPod3,1

The following images show the output in Xcode (running in the simulator) and on my 3G iphone:

31 Comments

  1. Thanks for this. I was looking how to do this but never quite got there – thought it would be something that was available in the normal SDK without having to dig about in sysctl.

  2. Yeah, Thanks John.
    Could you possibly upload the project file, so that others can dig deeper into the code, settings, etc.

    Thanks!

    Terrance

  3. Hi Terrance,

    Using the code is as easy as creating a new file with the name UIDevice+machine.h and add the interface definition shown above. Then create another file: UIDevice+machine.m and paste in the implementation code. Save these files and import into your project (or you can create the files within Xcode).

    To use the new class, add #import “UIDevice+machine.h” to your class and call [[UIDevice currentDevice] machine]

    John

  4. Excellent!
    Thanks again John!

    Terrance

  5. Thanks for this. Was googling around for a solution and yours was the simplest, and it works.

  6. Thanks for a great tutorial

    Is this App Store Safe?

    /Olof

    • olof, this could does not use private api’s so I assume there are no worries regarding app approval

  7. Updated device list:

    iPhone Simulator == i386
    iPhone == iPhone1,1
    3G iPhone == iPhone1,2
    3GS iPhone == iPhone2,1
    1st Gen iPod == iPod1,1
    2nd Gen iPod == iPod2,1

    1st Gen iPad == iPad1,1
    iPhone 4 == iPhone3,1

    I imagine the iPod Touch 4 will be == iPod3,1
    and the 2011 next generation iPad will be == iPad2,1

  8. fantastic! any way to tap into this info via JavaScript in safari?

  9. just another reason to love categories.
    such a great invention

  10. Just a quick update to the code.

    NSString *machine = [NSString stringWithCString:name];

    The stringWithCString appears to be deprecated. Just swap that line with:

    NSString *machine = [NSString stringWithUTF8String:name];

  11. this is a little bit nit picky, but I’d recommend creating the temp string on the stack instead of on the heap with malloc. I doubt hw.machine will ever return a string larger than 128 or so.

    this method would then be fewer lines of code:

    size_t size;
    char name[128];
    sysctlbyname("hw.machine", name, &amp;size, NULL, 0);
    return [[NSString stringWithUTF8String:name] autorelease];
    • Instead of shortening the code (and breaking in case someone does decide hw.machine should be something longer than 128), I suggest that it may be a good idea to even add a check for failure of sysctlbyname() to the original code. In case Apple removes “hw.machine” on a future iOS or on a future device, the app would cease to function on that device.

  12. That’s a great code. Thanks a lot!!!
    By the way the iPod Touch 4 is identified as iPod4,1

  13. This code works great, but iPad2 is not recognized properly with iPad2,1 or iPad1,2…. I ended up checking for the small screen and retina display and just using an else to handle the iPad cases, which is working great. Just wanted to let you guys know, and I’d be curious to know what the actual param is to get the iPad2 for future reference, never know when you’ll need it!

    • Hey, bsd2,

      I’d love to know the device name for iPad and iPad2. If you’re using the above code, you could use:

      NSLog(“%@”, [UIDevice machine]);

      to find out the device name, as returned by sysctl “hw.machine”. Please tell us what the device name is on both iPads!

  14. Thanks Ivan.

    Ipad1 = “iPad1,1”
    Ipad2 = “iPad2,3”

    But is every iPad2 the same hardware code?

    Thanks,
    Jeremy

  15. Here’s some code you can use with everything laid out nicely with defines… this is UIDevice+machine.h
    UIDevice+machine.m (remains unchanged..)
    ———————————————–
    #define IPHONE_SIM @”i386″ //480×320 res

    #define IPHONE_BASE@”iPhone1,1″ //480×320 res
    #define IPHONE_3G @”iPhone1,2″ //480×320 res
    #define IPHONE_3GS@”iPhone2,1″ //480×320 res
    #define IPHONE_4G @”iPhone3,1″ //960×640 res (retina display)

    #define IPOD_GEN1 @”iPod1,1″ //480×320 res
    #define IPOD_GEN2 @”iPod2,1″ //480×320 res
    #define IPOD_GEN3 @”iPod3,1″ //480×320 res
    #define IPOD_GEN4 @”iPod4,1″ //960×640 res (retina display)

    #define IPAD1 @”iPad1,1″ //1024×768 res (hd)
    #define IPAD2 @”iPad2,3″ //1024×768 res (hd)

    @interface UIDevice(machine)
    – (NSString *)machine;
    @end

    ———————— (CheckScreen.h)———————-
    @interface CheckScreen : NSObject

    {
    @public
    BOOL isSmallScreen;
    BOOL isRetinaScreen;
    CheckScreen *checkScreen;
    }

    -(BOOL)isSmallScreen;
    -(BOOL)isRetinaScreen;

    @end

    ———————— (CheckScreen.m)———————-
    #import “CheckScreen.h”
    #import “UIDevice+machine.h”

    @implementation CheckScreen

    – (BOOL)isSmallScreen
    {

    if ([[[UIDevice currentDevice] machine] isEqualToString: IPHONE_SIM] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPHONE_BASE] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPHONE_3G] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPHONE_3GS] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPOD_GEN1] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPOD_GEN2] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPOD_GEN3] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPHONE_4G] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPOD_GEN4]
    )

    {
    isSmallScreen = 1;
    }

    else
    {
    isSmallScreen = 0;
    }

    return isSmallScreen;

    }

    – (BOOL)isRetinaScreen
    {

    if ([[[UIDevice currentDevice] machine] isEqualToString: IPHONE_4G] ||
    [[[UIDevice currentDevice] machine] isEqualToString: IPOD_GEN4])

    {
    isRetinaScreen = 1;
    }

    else
    {
    isRetinaScreen = 0;
    }

    return isRetinaScreen;

    }

    @end

    ———————————————-(then ask the device to do something anywhere…)

    CheckScreen *checkScreen = [[CheckScreen alloc] autorelease];

    if([checkScreen isSmallScreen]) {
    do something….
    }

    else{
    do something….
    }

  16. According to http://www.everymac.com iPad2,2 represents an iPad 2 (Wi-Fi/GSM/A-GPS) for example of AT&T and iPad2,3 represents an iPad 2 (Wi-Fi/CDMA/A-GPS) for example of Verizon

  17. iPhone 4S identifies itself as “iPhone4,1”.
    on Lion the simulator identifies itself as “x86_64”.

  18. Thank you John.

    Can you help to get network type (GSM/CDMA) and is it possible to get LAC?

Comments are closed.