#if check(预处理宏)用于区分iPhone和iPad

11

是否有构建预处理宏可以使用#if或#ifdef检查,以确定我的当前Xcode项目正在构建的是iPhone还是iPad?

编辑

正如几个答案所指出的那样,通常应用程序是通用的,同一二进制文件可以在两个设备上运行。这些非常相似的设备之间的条件行为应该在运行时而不是编译时解决。

5个回答

25

3
这实际上是在苹果公司的WWDC讲座中提出的建议。 - Vojto
为什么要使用宏?没有人支持低于3.2的iOS版本,因此UI_USER_INTERFACE_IDIOM的优势是不存在的。 - Tricertops
这个问题和答案来自2010年。 - Lou Franco
@LouFranco 抱歉,下次我会检查日期。 - Tricertops

9
NSString *deviceType = [UIDevice currentDevice].model;

if([deviceType isEqualToString:@"iPhone"]) {
    //iPhone
}
else if([deviceType isEqualToString:@"iPod touch"]) {
    //iPod Touch
}
else {
    //iPad
}

据我所知,您不能使用#if或#ifdef来实现此操作,但是由于Obj-C是C的严格超集,因此支持该功能。
相关: 使用iPhone SDK确定设备(iPhone、iPod Touch)

这正是我担心的,因为它们基本运行相同的应用程序。 - Justin Meiners
4
由于“通用二进制文件”同时构建了两种应用程序,因此无法在编译时进行检查。如果您构建不同的iPad和iPhone应用程序,则可以通过为不同目标定义自己的编译器宏等多种方式来进行检查。 - tc.
2
这样做不安全!明天苹果可能会更改字符串,导致你的应用程序无法正常工作。从UIDevice中获取userInterfaceIdiom属性是最安全的方法。 - SEQOY Development Team
谢谢大家的评论!我现在明白了条件构建和运行时检查的危险。 - Justin Meiners
1
不安全。你不应该比较字符串,而是使用UIDevice API。 - DZenBot
显示剩余3条评论

8

无法确定您的应用程序是为iPhone还是iPad构建的。预处理器#if指令在构建期间解析。一旦您的应用程序被构建并标记为通用,它必须在两个设备上正确运行。在构建过程中,没有人知道它将被安装在哪里,一个构建版本可以安装在两个设备上。

但是您可能想要执行以下操作之一:

  1. Detect device model during runtime.

    To do this, use [[UIDevice currentDevice] model] and compare to iPhone, iPod touch or iPad strings. This will return you correct device even when running in compatibility mode on iPad (for iPhone-only apps). This can be usefull for usage analytics.

  2. Detect user interface idiom during runtime.

    This is what everyone checks for, when providing different content for iPhone and iPad. Use [[UIDevice currentDevice] userInterfaceIdiom] and compare to UIUserInterfaceIdiomPhone or UIUserInterfaceIdiomPad. You may want to make convenience methods like this:

    @implementation UIDevice (UserInterfaceIdiom)
    
    - (BOOL)iPhone {
        return (self.userInterfaceIdiom == UIUserInterfaceIdiomPhone);
    }
    + (BOOL)iPhone {
        return [[UIDevice currentDevice] iPhone];
    }
    
    - (BOOL)iPad {
        return (self.userInterfaceIdiom == UIUserInterfaceIdiomPad);
    }
    + (BOOL)iPad {
        return [[UIDevice currentDevice] iPad];
    }
    
    @end
    

    Then you can use:

    if ([[UIDevice currentDevice] iPhone]) { }
    // or
    if ([UIDevice iPhone]) { }
    // or
    if (UIDevice.iPhone) { }
    

我两年前就问过这个问题,现在我明白了何时应该使用运行时和编译时检查。感谢你的回答!我相信它会帮助其他人。 - Justin Meiners
哦,日期!希望它能帮助到某人。 - Tricertops

0

Swift 更新:

无法使用预处理器。将全局函数设为

func IS_IPAD() -> Bool { 
( return (UIDevice.respondsToSelector(Selector("userInterfaceIdiom"))) && (UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad) )}

2
正如UI_USER_INTERFACE_IDIOM()宏所记录的那样,如果您部署的iOS版本低于3.2,则只需要检查选择器。使用Swift就不需要这样做了。 ;) - Christopher Rogers

0

我在AppleTV 4上使用以下代码,因为UIUserInterfaceIdiomUnspecified似乎不起作用,也找不到其他枚举值:

#ifdef TARGET_OS_IOS
CGSize result = [[UIScreen mainScreen] bounds].size;
    if(result.width == 1920) {
        NSLog(@"tvOS");
    }
#endif

在黑暗时代之前,我曾经在iPad等设备上使用过这个技巧-OB1,哈哈晚安。但是你可以将这种类似的技术用于其他屏幕尺寸。


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