Determine Device Type – 3G or 3GS / iPod First or Second Generation
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:


Related posts:
- Is Application Running on iPhone or iPod touch
- C++ on iPhone: Part 3, Run Time Type Identification
- Where Was Touch – Determine if Touch/Point is Within Rectangle



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.
[Reply]
Yeah, Thanks John.
Could you possibly upload the project file, so that others can dig deeper into the code, settings, etc.
Thanks!
Terrance
[Reply]
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
[Reply]
Thank you verrrry much.
[Reply]
Excellent!
Thanks again John!
Terrance
[Reply]
Thanks for this. Was googling around for a solution and yours was the simplest, and it works.
[Reply]
Thank you for this. You’re a genius :)
[Reply]
Thanks for a great tutorial
Is this App Store Safe?
/Olof
[Reply]
John Muchow Reply:
January 11th, 2010 at 1:50 pm
olof, this could does not use private api’s so I assume there are no worries regarding app approval
[Reply]
Great! Thanks for sharing this code.
/Olof
[Reply]
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
[Reply]
fantastic! any way to tap into this info via JavaScript in safari?
[Reply]
just another reason to love categories.
such a great invention
[Reply]
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];
[Reply]
Thank you John Muchow. And TY Joe for update.
[Reply]
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:
[Reply]
Ivan Vučica Reply:
February 22nd, 2011 at 5:48 am
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.
[Reply]
That’s a great code. Thanks a lot!!!
By the way the iPod Touch 4 is identified as iPod4,1
[Reply]
Great Thanks!!
[Reply]
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!
[Reply]
Ivan Vučica Reply:
June 9th, 2011 at 5:00 am
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!
[Reply]
Thanks Ivan.
Ipad1 = “iPad1,1″
Ipad2 = “iPad2,3″
But is every iPad2 the same hardware code?
Thanks,
Jeremy
[Reply]
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….
}
[Reply]
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
[Reply]
iPhone 4S identifies itself as “iPhone4,1″.
on Lion the simulator identifies itself as “x86_64″.
[Reply]