iPhone或iPad上运行的API判断

32

有没有一个API可以在运行时检查你是否在iPhone或iPad上运行?

我能想到的一种方法是使用:

[[UIDevice currentDevice] model];

检测字符串@"iPad"的存在 - 看起来有点脆弱。

在3.2 SDK中,我看到UIDevice也有一个属性,这正是我要找的,但不适用于3.2之前的版本(显然):

[[UIDevice currentDevice] userInterfaceIdiom]; 

除了检查 @"iPad" 的存在以外,是否还有其他方法来创建一个通用应用程序?

5个回答

41

查看UI_USER_INTERFACE_IDIOM

返回当前设备支持的界面风格。

返回值
如果设备是iPhone或iPod touch,则返回UIUserInterfaceIdiomPhone,如果设备是iPad,则返回UIUserInterfaceIdiomPad

UIUserInterfaceIdiom

应在当前设备上使用的界面类型

typedef enum {
   UIUserInterfaceIdiomPhone,
   UIUserInterfaceIdiomPad,
} UIUserInterfaceIdiom;

明白了 - 我可以使用 respondsToSelector:@selector(userInterfaceIdiom) 代替检查字符串"iPad"的存在。 谢谢! - Eric
7
使用该宏 - 较新的操作系统将响应该选择器,但不一定是iPad。 - Andiih
1
好的,我正在学习。 :) 我的 #失败:我一直在使用模拟器通过在3.2和3.1之间切换Active SDK来在iPhone和iPad之间切换 - 当Active SDK为3.1时,它不再编译。然后我用一些咖啡因震动了神经元,并在其周围插入了 #ifdef UI_USER_INTERFACE_IDIOM...无论如何,感谢Andiih的跟进 - 如果我刚刚将我的 #失败复杂化为比 #worsethanfailure 更糟糕的东西,让我知道。 :) - Eric
1
仅供交叉链接参考:https://dev59.com/gXE85IYBdhLWcg3w3Xdp - Dan Rosenstark
5
请注意:如果iPad用户正在运行仅限于iPhone的应用程序(即非通用应用),UI_USER_INTERFACE_IDIOM函数将报告该设备为iPhone。 - Jason Fuerstenberg
@Andiih最好包含一些代码源而不是链接。 - bugfixr

15

仅供参考:

@property (nonatomic, readonly) BOOL isPhone;

-(BOOL)isPhone {
    return (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone);
}

或者使用 #define

#define IS_PHONE  (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
然而,如果你在代码中到处使用isPhone,那通常是不好的实践。使用工厂模式和多态性来保持if语句的封装性,这样你就可以为手机或iPad创建对象,然后使用这些对象进行操作。

添加

我现在在我的代码中到处使用此解决方案。它将一个标准的工厂模式添加到了alloc中。

#define ALLOC_PER_DEVICE()  id retVal = nil; \
                        NSString *className = NSStringFromClass(self);\
                        if (IS_PHONE && ![className hasSuffix:@"Phone"]) {\
                            className = [NSString stringWithFormat:@"%@Phone", className];\
                            Class newClass = NSClassFromString(className);\
                            retVal = [newClass alloc];\
                        }\
                        if (!retVal)\
                            retVal = [super alloc];\
                        assert(retVal != nil);\
                        return retVal\

然后我的分配看起来像这样:

+alloc { ALLOC_PER_DEVICE(); }

我添加了一个名为TheClassPhone的子类,用于手机版本。

注意:由于在Objective-C中没有多重继承,因此使用继承来解决问题有些过度评价(即如果您有子类的子类,则不起作用)。在需要时使用好的if语句就行了。


嗨,我是Objective-C的学习者。只是想知道为什么不一定要创建一个工具类并添加一个“isPhone”静态方法,以便我可以在整个项目中使用if([utilities isPhone]){ /* iphone stuff / } else { / ipad stuff */ }?另外,为什么要将方法定义为属性? - David Zorychta
实用工具类与类方法很好。我将其定义为属性,因为我想以这种方式使用它。 - Dan Rosenstark
如果你的Utilities类是单例模式,那么你可以使用utilities isPhone,否则就要创建类方法。单例模式绝对是推荐的方式。方法和属性是相同的。Objective-C非常灵活。 - Dan Rosenstark

1
您可以使用以下代码来检查应用程序是否在iPhone或iPad上运行:
- (NSString *)deviceModel
{
    struct utsname systemInfo;
    uname(&systemInfo);
    return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}

- (NSString *) platformString
{
    NSString *platform = [self deviceModel];
    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone_2G";
    else if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone_3G";
    else if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone_3GS";
    else if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone_4";
    else if ([platform isEqualToString:@"iPhone3,3"])    return @"Verizon_iPhone_4";
    else if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone_4S";
    else if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone_5";
    else if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone_5";
    else if ([platform isEqualToString:@"iPod1,1"])      return @"iPod_Touch 1G";
    else if ([platform isEqualToString:@"iPod2,1"])      return @"iPod_Touch 2G";
    else if ([platform isEqualToString:@"iPod3,1"])      return @"iPod_Touch 3G";
    else if ([platform isEqualToString:@"iPod4,1"])      return @"iPod_Touch 4G";
    else if ([platform isEqualToString:@"iPad1,1"])           return @"iPad_1G";
    else if ([platform isEqualToString:@"iPad2,1"])      return @"iPad_2(WiFi)";
    else if ([platform isEqualToString:@"iPad2,2"])      return @"iPad_2(GSM)";
    else if ([platform isEqualToString:@"iPad2,3"])      return @"iPad_2(CDMA)";
    else if ([platform isEqualToString:@"iPad3,1"])      return @"iPad_3";
    else if ([platform isEqualToString:@"iPad3,2"])      return @"iPad_3(GSM/CDMA)";
    else if ([platform isEqualToString:@"iPad3,3"])      return @"iPad_3(GSM)";
    else if ([platform isEqualToString:@"iPad3,4"])      return @"iPad_3(GSM)";
    else if ([platform isEqualToString:@"iPad2,5"])      return @"iPad_mini_1G";
    else if ([platform isEqualToString:@"i386"])         return @"Simulator";
    else if ([platform isEqualToString:@"x86_64"])       return @"Simulator";
    return platform;
}

1

4
很难确定您在这里回答了什么。要么删除它,要么修复它,也许? - Dan Rosenstark

1
检查userInterfaceIdiom属性是否存在,使用respondsToSelector:。如果不存在,则我们在一个3.2之前的设备上,因此不是iPad。 如果userInterfaceIdiom存在,则使用它。
编辑:......显然这就是UI_USER_INTERFACE_IDIOM()宏所做的事情,因此改用它。 :)

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