Ad

Our DNA is written in Swift
Jump

Determining the Hardware Model

Not all Apple Hardware is created equal. For some apps you need to distinguish between different models of iPhones and iPod Touch. But when you query the model property of UIDevice you don’t get enough information to really know what hardware your app is running on.

With a little bit of googling I found an article on Ars Technica explaining how the pros are getting the kind of information that we regular dev guys dream of having at our fingertips. It basically uses barely documented system calls to get the infamous model string from which you can infer the real device model.

We are talking about sysctlbyname which Apple even documents as a standard C library function call to “get or set system information”. iPhone Dev crack Erica Sadun made this UIDevice category extension. We are inspecting it with awe as we see the magic unfold.

I took the liberty to expand the class to also take iPhone 3GS into account.

UIDevice-hardware.h

#import
 
#define IPHONE_1G_NAMESTRING @"iPhone 1G"
#define IPHONE_3G_NAMESTRING @"iPhone 3G"
#define IPHONE_3GS_NAMESTRING @"iPhone 3GS"
#define IPOD_1G_NAMESTRING @"iPod touch 1G"
#define IPOD_2G_NAMESTRING @"iPod touch 2G"
 
@interface UIDevice (Hardware)
- (NSString *) platform;
- (NSString *) platformString;
@end

UIDevice-hardware.m

#import "UIDevice-hardware.h"
#include 
#include 
 
@implementation UIDevice (Hardware)
 
/*
 Platforms
 iPhone1,1 = iPhone 1G
 iPhone1,2 = iPhone 3G
 iPhone2,1 = iPhone 3GS
 iPod1,1   = iPod touch 1G
 iPod2,1   = iPod touch 2G
 */
 
- (NSString *) platform
{
	size_t size;
	sysctlbyname("hw.machine", NULL, &size, NULL, 0);
	char *machine = malloc(size);
	sysctlbyname("hw.machine", machine, &size, NULL, 0);
	NSString *platform = [NSString stringWithCString:machine];
	free(machine);
	return platform;
}
 
- (NSString *) platformString
{
	NSString *platform = [self platform];
	if ([platform isEqualToString:@"iPhone1,1"]) return IPHONE_1G_NAMESTRING;
	if ([platform isEqualToString:@"iPhone1,2"]) return IPHONE_3G_NAMESTRING;
	if ([platform isEqualToString:@"iPhone2,1"]) return IPHONE_3GS_NAMESTRING;
	if ([platform isEqualToString:@"iPod1,1"])   return IPOD_1G_NAMESTRING;
	if ([platform isEqualToString:@"iPod2,1"])   return IPOD_2G_NAMESTRING;
	return NULL;
}
@end

Having established the true machine type of your device you can now proceed to customize your app intelligently and disable features that older models don’t support. For example you could remove all traces of the vibration option if you are dealing with first generation iPod Touch.

Checking for the availability of a camera would probably be better done by calling isSourceTypeAvailable on the image picker.

if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
	NSLog(@"Get an iPhone, man!");
}

Using the recommended method for determining availability of a microphone is slightly more tricky, Apple says to use the AVAudioSession class for this purpose which is available from iPhone OS Version 3.0 onward.

Using the above class might enable you to make educated decisions based on other hardware presence or absence. Did you know that the first generation iPhone cannot properly render very high frequencies over the internal speaker? Now you know and what to do about it.


Categories: Recipes

0 COmments »

  1. Thanks!

    Do you know what the name string is for a “late 2009” Touch?

  2. No. I don’t have such a device.