检测特定的iPhone/iPod touch型号。

108

可能是重复问题:
确定带有iOS的设备(iPhone、iPod Touch)

我正在制作一个利用iPhone(和可能是iPod touch第二代)的点对点蓝牙功能的游戏。然而,为了防止用户尝试在iPod 1代和iPhone 2G上进行多人游戏,我需要检查具体的设备型号。

[[UIDevice currentDevice] model]只会告诉我设备是“iPhone”还是“iPod touch”。是否有一种方法可以检查特定的设备型号,例如:“iPhone 3GS”,“iPod touch第一代”或其他内容。

编辑:

有一个UIDevice类别(我认为它是由Erica Sadun创建的,我不为此负责),它使用以下代码获取特定的设备型号。您可以在此处找到整个类别以及其他有用的内容:https://github.com/erica/uidevice-extension

#include <sys/types.h>
#include <sys/sysctl.h>

@implementation UIDevice (Hardware)

/*
 Platforms
 iPhone1,1 -> iPhone 1G
 iPhone1,2 -> iPhone 3G 
 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 encoding:NSUTF8StringEncoding];
  free(machine);
  return platform;
}

这个已经生效,而且使用它的应用程序最近已经在AppStore中获得了批准。


在这个SO问题<a href="http://stackoverflow.com/questions/786026/how-do-you-detect-iphone-v-iphone-3g-using-obj-c">中</a>, 一个链接被发布到<a href="http://github.com/ars/uidevice-extension/tree/master">这个</a>网站。HTH - drvdijk
7
非常重要:苹果建议不要使用这段代码。这是因为在某些情况下可能会出现错误检测。请查看WWDC 2011会议第123场,3分30秒处,您将会看到他们展示了这段准确的代码,并告诉大家不要使用它。 - Thiago Peres
@Lookez,我们需要使用什么代码? - Rodrigo
4
我看了那个视频。现在不推荐使用那种代码来检测iPad(因为我们现在有UI_USER_INTERFACE_IDIOM来检测它),但是没有提到使用它来确定具体的硬件型号。 - zubko
是的,在“某些情况下可能会错误地检测到”这一点上并不准确,它总是能够正确地检测。你只需要为未来保留你的代码,并且不要有一些悬空的“else”条件,以默认特定版本。 - Cbas
6个回答

154

你可以使用sys/utsname.h中的uname来获取设备的型号。例如:

#import <sys/utsname.h>

NSString*
machineName()
{
    struct utsname systemInfo;
    uname(&systemInfo);

    return [NSString stringWithCString:systemInfo.machine
                              encoding:NSUTF8StringEncoding];
}

结果应该是:

在模拟器上: @"i386"
在iPod Touch上:
    第一代:@"iPod1,1"
    第二代:@"iPod2,1"
    第三代:@"iPod3,1"
    第四代:@"iPod4,1"
在iPhone上:
    第一代:@"iPhone1,1"
    iPhone 3G:@"iPhone1,2"
    iPhone 3GS:@"iPhone2,1"
在iPad上:
    第一代:@"iPad1,1"
    iPad 2:@"iPad2,1"
    iPad 3 (又称为新iPad):@"iPad3,1"
在iPhone上:
    iPhone 4:@"iPhone3,1"
    iPhone 4S:@"iPhone4,1"
    iPhone 5:@"iPhone5,1" 或 @"iPhone5,2"

11
针对模拟器的架构是“x86_64”。 - João Nunes
1
我不确定是我的问题还是其他原因,但在开发时我测试了4、4s和5,这对我有效,但在生产环境中它彻底失败了,似乎根本没有起作用,这导致了很多问题。 - Dave Chenell
“Dave Chenell”,在生产环境中,[NSString stringWithCString] 使用的编码是否有误?因为它可能会受到环境的影响而返回nil。 - Skrew
6 Plus:iPhone7,1 6:iPhone7,2 5S:iPhone6,2 - static0886
这段代码在Xcode 7.3上仅在iPhone 4设备上构建时崩溃。 - Sti
显示剩余10条评论

66

最全面的UIDevice(硬件)类别可能是Erica Sadun的http://github.com/erica/uidevice-extension/

[[UIDevice currentDevice] platformType]   // ex: UIDevice4GiPhone
[[UIDevice currentDevice] platformString] // ex: @"iPhone 4G"

6
今天它无法工作。我在[UIDevice currentDevice]中找不到platformType和platformString。 - Yi Jiang
@RobertYiJiang,你是否已经添加了答案中链接的Github项目中的类? - rckoenes

23
如果新版本发布,你将使用上一个已知设备的标识符来进行识别。
#include <sys/types.h>
#include <sys/sysctl.h>

- (NSString *)getModel {
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *model = malloc(size);
    sysctlbyname("hw.machine", model, &size, NULL, 0);
    NSString *sDeviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];
    free(model);                              
    if ([sDeviceModel isEqual:@"i386"])      return @"Simulator";  //iPhone Simulator
    if ([sDeviceModel isEqual:@"iPhone1,1"]) return @"iPhone1G";   //iPhone 1G
    if ([sDeviceModel isEqual:@"iPhone1,2"]) return @"iPhone3G";   //iPhone 3G
    if ([sDeviceModel isEqual:@"iPhone2,1"]) return @"iPhone3GS";  //iPhone 3GS
    if ([sDeviceModel isEqual:@"iPhone3,1"]) return @"iPhone4 AT&T";  //iPhone 4 - AT&T
    if ([sDeviceModel isEqual:@"iPhone3,2"]) return @"iPhone4 Other";  //iPhone 4 - Other carrier
    if ([sDeviceModel isEqual:@"iPhone3,3"]) return @"iPhone4";    //iPhone 4 - Other carrier
    if ([sDeviceModel isEqual:@"iPhone4,1"]) return @"iPhone4S";   //iPhone 4S
    if ([sDeviceModel isEqual:@"iPhone5,1"]) return @"iPhone5";    //iPhone 5 (GSM)
    if ([sDeviceModel isEqual:@"iPod1,1"])   return @"iPod1stGen"; //iPod Touch 1G
    if ([sDeviceModel isEqual:@"iPod2,1"])   return @"iPod2ndGen"; //iPod Touch 2G
    if ([sDeviceModel isEqual:@"iPod3,1"])   return @"iPod3rdGen"; //iPod Touch 3G
    if ([sDeviceModel isEqual:@"iPod4,1"])   return @"iPod4thGen"; //iPod Touch 4G
    if ([sDeviceModel isEqual:@"iPad1,1"])   return @"iPadWiFi";   //iPad Wifi
    if ([sDeviceModel isEqual:@"iPad1,2"])   return @"iPad3G";     //iPad 3G
    if ([sDeviceModel isEqual:@"iPad2,1"])   return @"iPad2";      //iPad 2 (WiFi)
    if ([sDeviceModel isEqual:@"iPad2,2"])   return @"iPad2";      //iPad 2 (GSM)
    if ([sDeviceModel isEqual:@"iPad2,3"])   return @"iPad2";      //iPad 2 (CDMA)

    NSString *aux = [[sDeviceModel componentsSeparatedByString:@","] objectAtIndex:0];

//If a newer version exist
    if ([aux rangeOfString:@"iPhone"].location!=NSNotFound) {
        int version = [[aux stringByReplacingOccurrencesOfString:@"iPhone" withString:@""] intValue];
        if (version == 3) return @"iPhone4"
        if (version >= 4) return @"iPhone4s";

    }
    if ([aux rangeOfString:@"iPod"].location!=NSNotFound) {
        int version = [[aux stringByReplacingOccurrencesOfString:@"iPod" withString:@""] intValue];
        if (version >=4) return @"iPod4thGen";
    }
    if ([aux rangeOfString:@"iPad"].location!=NSNotFound) {
        int version = [[aux stringByReplacingOccurrencesOfString:@"iPad" withString:@""] intValue];
        if (version ==1) return @"iPad3G";
        if (version >=2) return @"iPad2";
    }
    //If none was found, send the original string
    return sDeviceModel;
}

1
它仍然可以工作!你需要添加 #include <sys/types.h> #include <sys/sysctl.h> - Yoga
无法工作,输出为 x86_64。 - user5633758

4
BOOL hasHighResScreen = NO;
if ([UIScreen instancesRespondToSelector:@selector(scale)]) {
    CGFloat scale = [[UIScreen mainScreen] scale];
    if (scale > 1.0) {
        hasHighResScreen = YES;
    }
}

那并没有返回确切的型号,只是它有一个“高清”或“标清”屏幕。 - Dimitris
1
这对我来说非常完美。我只需要知道设备是否具有高分辨率即可。 - Sam B

4

iPhone 4的内部产品代码分别是iPhone3,1和iPhone3,2。
iPhone 4S的内部产品代码是iPhone4,1。
iPad 2的内部产品代码取决于版本(GSM等),分别是iPad2,1、iPad2,2和iPad2,3。
iPad 3的内部产品代码取决于版本(GSM等),分别是iPad3,1、iPad3,2和iPad3,3。

详见Iphone secrets(向下滚动至“internal product codes”)。

另一个好的信息来源是:everyiphone.com


-11
NSString* valueDevice = [[UIDevice currentDevice] model];

然后检查字符串是否等于您要查找的设备,例如:

if(value==@"iPod1,1" ) 
{}

然后你就可以开始了


1
希望有人能说一下为什么这个代码有 -11 的值,但是没有注释说明原因。 - Brad Moore
1
代码[[UIDevice currentDevice] model]只会返回“iPhone”或“iPad”,而不是型号编号。 - Chris Stillwell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接