如何在 iPhone OS SDK < 3.2 中使用 UI_USER_INTERFACE_IDIOM() 函数

32

苹果建议使用以下代码来检测是否在iPad或iPhone/iPod Touch上运行:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  // The device is an iPad running iPhone 3.2 or later.
  // [for example, load appropriate iPad nib file]
}
else {
  // The device is an iPhone or iPod touch.
  // [for example, load appropriate iPhone nib file]
}
问题在于UI_USER_INTERFACE_IDIOM()和UIUserInterfaceIdiomPad在3.2之前的SDK中没有被定义。这似乎完全违背了这样一个函数的目的。它们只能在iPhone OS 3.2上编译和运行(iPhone OS 3.2只能在iPad上运行)。因此,如果你使用UI_USER_INTERFACE_IDIOM(),结果将始终指示为iPad。
如果你包含这段代码并针对OS 3.1.3目标(最近的iPhone / iPod Touch OS)来测试你的iPhone绑定的通用应用程序代码,当编译iPhone模拟器3.1.3时,你将会得到编译器错误,因为这些符号在3.1.3或更早版本中没有被定义。
如果这是苹果公司推荐的运行时设备检测方法,那么我做错了什么?有人成功地使用这种设备检测方法吗?
8个回答

24

14

这是我使用的代码:

- (BOOL) amIAnIPad {
    #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)
        if ([[UIDevice currentDevice] respondsToSelector: @selector(userInterfaceIdiom)])
            return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
    #endif
    return NO;
}

这个条件编译可以让你继续为3.0模拟器构建项目。然后它检查UIDevice类是否响应选择器。如果其中任何一个失败,那么这不是一个iPad。


那就是如果你想编译为3.0版本。你应该像drootang所说的那样,编译为3.2并在3.0设备上运行它,因为3.2是你提交到AppStore的版本。 - conradev
我同意,但在构建3.2版本时,无法在iPHONE模拟器(相对于iPad)上进行测试。如果您想在两个模拟器上进行测试,您必须使用这种诡计。 - Ben Gottlieb

7
如果这是苹果推荐的运行时设备检测方法,那我做错了什么?有没有人成功地使用这种方法来检测设备?
以下是运行时检测的解决方案:
#define isIPhone (![[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)

之后你可以在代码的任何地方轻松测试它:

if (isIPhone) { ... }

与使用#if / #ifdef的区别在于,这是运行时测试,而#if是编译时测试。
我认为运行时测试更好,因为在这种情况下,您可以使用一个可执行文件适用于任何操作系统版本。如果您使用编译时检查,则需要为不同的操作系统版本生成不同的可执行文件。
如果您的问题是编译时错误,那么您只需针对最新版本的SDK进行编译(还请参阅如何在iOS中访问弱链接框架?)。

5

我不使用任何编译器相关的东西,而是使用:

- (BOOL)deviceIsAnIPad {
if ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)])
    //We can test if it's an iPad. Running iOS3.2+
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
        return YES; //is an iPad
    else 
        return NO; //is an iPhone
else 
    return NO; //does not respond to selector, therefore must be < iOS3.2, therefore is an iPhone
}

5

我认为答案很简单,就是不要试图在iPhone模拟器3.1.3或更早版本上运行代码。始终使用3.2 SDK进行编译。iPhone模拟器3.2将为您提供iPad模拟器,或者编译iPhone设备3.2并将应用程序放在手机上进行测试。

没有办法使用3.2 SDK编译并使用3.1.3或更早版本的模拟器。


5
可以的。您可以使用3.2 SDK进行构建,然后将当前目标更改为iPhone 3.1,最后选择“运行”或“调试”,而不是重新构建它。 - John Wang

2

使用这个关键词进行声明:

#ifdef UI_USER_INTERFACE_IDIOM
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define IS_IPAD false
#endif

然后按以下方式使用检查

#define DetailLabel_PosX (IS_IPAD ? 200 : 160)

还有一些检查 iPhone 5 的定义。

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#define IOS_OLDER_THAN_6 ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0 )
#define IOS_NEWER_OR_EQUAL_TO_6 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0 )

0

UI_USER_INTERFACE_IDIOM()和UIUserInterfaceIdiomPad可用于iOS3.2及以上版本,重要的是“以上”部分。当然,iOS3.2仅适用于iPad,但iOS4.0及更高版本可在iPhone和iPad上运行,因此检查并不像你想象的那样毫无意义。


0
这似乎完全违背了这样一个函数的目的。它们只能在iPhone OS 3.2上编译和运行(iPhone OS 3.2只能在iPad上运行)。因此,如果您可以使用UI_USER_INTERFACE_IDIOM(),结果将始终指示iPad。
这是完全不正确的。它可以在Base SDK 3.2上编译,但如果您适当地设置部署目标,它可以在任何操作系统上运行。

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