在兼容模式下运行的iPad上如何检测iPhone应用程序

12

我的iPhone 应用程序不是通用的,但它有一个功能,我想要让在iPad上玩的人也能使用。有没有一种方式可以检测出您正在兼容模式下运行的iPad?UIDevice 用于检测机器规格的方法都返回在iPhone上获得的值(至少在模拟器上)。我唯一能想到的是检测OS 3.2,但这种技术不会长久有效。


3
“兼容性模式”是什么意思?这里用的是iOS系统,不是Windows XP。 - Brock Woolf
当您在iPad上运行非通用的iPhone应用时,它会在模拟的iPhone环境中运行。请原谅我不知道确切的术语。 - n8gray
是的,iPhone应用程序可以在iPad上运行。在这种情况下,您已经知道您构建了一个iPhone应用程序,您只需要检查是否在iPad上运行,参见我的答案。 - Brock Woolf
我可以补充一点,将iPad功能启用于iPhone应用程序目标似乎有些愚蠢。为什么不正确地做,将iPhone应用程序制作成通用二进制文件(iPad+iPhone)呢? - Brock Woolf
6
让我们来看看,创建一个真正的通用应用程序需要做出商业决策,放弃分别为 iPhone/iPad 版本开发,并购买一台价值500美元的硬件设备进行测试,并完全重构我的用户界面,包括所需的所有质量保证。启用一个功能只需要回答一个问题并编写两三行代码。在明天提交我的更新之前,我应该做哪一个? - n8gray
几年后,但是苹果自己的文档称之为"兼容模式"。在这篇 iAd 文档中,检查"创建通用应用程序"标题下的技术说明 TN2264,其中说:"在 iPad 上运行的 iPhone 应用程序处于兼容模式..." - leanne
4个回答

21

最初的回答在这里:https://dev59.com/C1LTa4cB1Zd3GeqPc7qb#14864400

由于非常简短,因此重新发布:

如果应用程序是在iPad上以模拟器模式运行的iPhone应用程序,则其userInterfaceIdiom将为Phone,但模型类型为iPad。 您可以使用以下代码进行检查:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
    [[[UIDevice currentDevice] model] hasPrefix:@"iPad"]) {
    // This app is an iPhone app running on an iPad
}

你的代码有误。在iPad上运行的iPhone应用程序中,UI_USER_INTERFACE_IDIOM()将等于ipad。 - Duck
@RubberDuck 我必须不同意你的评估。我已经创建了一个测试应用程序来测试此功能:https://github.com/michaelpatzer/TestEmulationMode。 - M-P
这很奇怪,因为在您的应用程序上,行为是符合预期的,但在我的两个应用程序中,我看到iPad作为成语!什么鬼!!! - Duck
我尽可能地让示例应用程序简单,以确保没有其他变量在起作用。如果您直接向我发送消息,我很乐意查看相关的应用程序以尝试调试问题。 - M-P
2
我已确认此代码在iOS 8上仍然正确。 - M-P
这是一个旧线程,但我在iOS12中遇到了UI_USER_INTERFACE_IDIOM的问题。对于在第三代iPad Pro上运行的仅限iPhone应用程序,如果我从[[UIScreen mainScreen] bounds]请求前端,则UI_USER_INTERFACE_IDIOM()将返回UIUserInterfaceIdiomPhone,但如果我稍后请求[[UIScreen mainScreen] bounds]则返回UIUserInterfaceIdiomPad。我假设请求屏幕边界只是调用触发UI_USER_INTERFACE_IDIOM()评估的示例吗? - HarryS

9

1) 使用 Erica Sadun 编写的 UIDevice-Extension 类。这是一个非常全面的类:http://github.com/erica/uidevice-extension/blob/master/UIDevice-Hardware.m

2) 或者你也可以使用 UIDevice 类方法:

[[UIDevice currentDevice] name]              // eg. "Brock's iPhone"
[[UIDevice currentDevice] model]             // eg. @"iPhone", @"iPod Touch"
[[UIDevice currentDevice] localizedModel]    // localized version of model
[[UIDevice currentDevice] systemName]        // eg. @"iPhone OS"
[[UIDevice currentDevice] systemVersion]     // eg. @"3.2"
[[UIDevice currentDevice] uniqueIdentifier]  // UDID, a unique string to identify the device

以上每行都会返回一个NSString。您可以进行字符串比较,如下所示:

NSString *model = [[UIDevice currentDevice] model];
NSLog(@"Current device model: \"%@\"", model);

3) 另一种方法:

http://www.drobnik.com/touch/2009/07/determining-the-hardware-model/ 您需要根据iPad的正确硬件编号进行修改。以上内容摘自上述链接:

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 <sys/types.h>
#include <sys/sysctl.h>

@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, &amp;size, NULL, 0);
 char *machine = malloc(size);
 sysctlbyname("hw.machine", machine, &amp;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

1
我没有iPad来测试,但在iPad模拟器中,[[UIDevice currentDevice] model]返回的是iPhone Simulator而不是iPad Simulator。我猜当在设备上运行时,它将返回iPhone而不是iPad。这是一个模拟的iPhone环境,所以这并不奇怪。hw.machine sysctl是一个有趣的建议,但在iPad模拟器上,它只返回i386。你知道在iPad上运行非通用iPhone应用程序时它返回什么吗? - n8gray
1
你不应该在模拟器上测试这个。你需要一个真实的设备,否则你怎么知道在现场环境中会发生什么? - Brock Woolf

3

如果您需要知道是否在iPad上运行iPhone应用程序,以便将界面缩小到iPhone 4S大小,值得注意的是,在12.9英寸的iPad上运行的iPhone应用程序以iPhone SE大小呈现。添加对主屏幕比例的检查将解决此问题。

var isSmalliPhoneAppRunningOniPad: Bool {
    return UIDevice.current.userInterfaceIdiom == .phone &&
           UIDevice.current.model.hasPrefix("iPad") && 
           UIScreen.main.scale == 2
}

3

你是否查看了"UIDevice.h" ?它有一个model属性,可以找出iPhone、iPod、iPad设备。

NSString *name; //例如:"我的iPhone"

NSString *model; //例如:@"iPhone",@"iPod Touch"

NSString *localizedModel; //本地化的model

NSString *systemName; //例如:@"iPhone OS"

NSString *systemVersion; //例如:@"2.0"

NSString *uniqueIdentifier; (已弃用) //一个基于各种硬件信息的每个设备唯一标识符的字符串


我没有iPad可供测试,但在iPad模拟器中,[[UIDevice currentDevice] model]返回的是iPhone Simulator而不是iPad Simulator - n8gray
我打印了[[UIDevice currentDevice] model],它返回了"iPad"。 :) - Adeem Maqsood Basraa
@n8gray:是的,模拟器有限制。只能在iOS设备上运行。 - Brock Woolf
已确认在实际设备上告诉我它的功能。 - n8gray

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