在 iPhone SDK 中检测视网膜屏幕/iPhone 4

Posted

技术标签:

【中文标题】在 iPhone SDK 中检测视网膜屏幕/iPhone 4【英文标题】:Detect retina screen/iPhone 4 in iPhone SDK 【发布时间】:2010-07-17 18:32:23 【问题描述】:

在我的应用程序中,我从网络(准确地说是从我的服务器)下载了一些图像,为了节省一些带宽,尤其是手机上的内存,我提供了两种分辨率:480x320 用于“旧”iPhone系列和 960x640 用于配备 Retina 显示屏的 iPhone 4。现在,我需要能够在应用程序在支持视网膜屏幕的设备上运行时从应用程序内部进行检测。我怎么能这样做?

我一直在考虑使用下面的代码 sn-p,它会返回一个特定的设备标识符,例如。 “iPhone3”,但我会将检测限制在 iPhone4 上,并且需要为任何后续配备视网膜显示屏的设备更新该代码。

size_t size;

// Set 'oldp' parameter to NULL to get the size of the data
// returned so we can allocate appropriate amount of space
sysctlbyname("hw.machine", NULL, &size, NULL, 0); 

// Allocate the space to store name
char *name = malloc(size);

// Get the platform name
sysctlbyname("hw.machine", name, &size, NULL, 0);

// Place name into a string
NSString *machine = [NSString stringWithCString:name];

有没有更好的解决方案(也许很明显但我错过了)?

【问题讨论】:

【参考方案1】:

刚刚在官方 Apple 开发者论坛上阅读了一些内容,这些问题已经在那里进行了详细讨论。对我来说最好的方法似乎是使用UIScreenscale 属性。虽然它仅在ios 4 及更高版本中可用,但它会告诉你你需要知道的一切,并且很可能在未来发挥更重要的作用(已经注意到 iPad 的 1024x768 屏幕分辨率正好是 32/15 * 480x320?)。

UIScreen.mainScreen.scale

如果您还有其他想法,请随时发布:)

【讨论】:

是的,使用这个,永远不要尝试查询你在哪个设备上运行,它只会以痛苦结束。 这是正确的方法,因为您不想为 iPhone 4 编写条件代码,而是为具有不同比例/分辨率的显示器编写条件代码。谁知道 iPod 什么时候才能进行视网膜治疗。 @Felix:希望在下一次更新中,预计在一月份。让我们的代码在没有任何调整的情况下神奇地支持它不是非常漂亮吗?因此 [UIScreen scale] 是最好的方法。【参考方案2】:

这里有一些代码可以在 iOS 3.x 和 4.x 中正确执行:

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

【讨论】:

请注意,如果 iPad 的“iphone 模拟器”模式以 2x 开始,这也将返回 true,这可能是也可能不是您想要的。 iPad 的“iphone 模拟器”的 2x 问题有解决方法吗?【参考方案3】:

Scott Gustafson 回答的一些更新:

如果我们需要区分iPad/Retina/iphone:

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
    
        CGFloat scale = [[UIScreen mainScreen] scale];

           if (scale > 1.0) 
           
                //iPad retina screen
             
           else
           
                //iPad screen
           
     
    else
    
         if ([UIScreen instancesRespondToSelector:@selector(scale)]) 
         
               CGFloat scale = [[UIScreen mainScreen] scale];

               if (scale > 1.0) 
               
                    if([[ UIScreen mainScreen ] bounds ].size.height == 568)
                    
                        //iphone 5
                    
                    else
                    
                        //iphone retina screen
                    
               
               else
               
                    //iphone screen
               
         
    

【讨论】:

【参考方案4】:

我通过这种方式获得了真实的屏幕尺寸(以像素为单位):

UIScreen *MainScreen = [UIScreen mainScreen];
UIScreenMode *ScreenMode = [MainScreen currentMode];
CGSize Size = [ScreenMode size]; // <--- Real screen size

【讨论】:

【参考方案5】:
- (BOOL)isRetina 

    BOOL isRetina = NO;

    if ([UIScreen instancesRespondToSelector:@selector(scale)]) 
        CGFloat scale = [[UIScreen mainScreen] scale];
        if (scale > 1.0) 
            isRetina = YES;
        
    

    return isRetina;



- (CGSize)sizeInPixels 

    CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
    CGSize screenSize = CGSizeMake(appFrame.size.width, appFrame.size.height);

    return [self isRetina] ? CGSizeMake(screenSize.width * 2, screenSize.height * 2) : screenSize;

【讨论】:

【参考方案6】:

跟着罗宾的回答走。另一个注意事项:如果您确实需要检查设备名称,只需使用 UIDevice 上的方法。

[[UIDevice currentDevice] model];
[[UIDevice currentDevice] systemName];
[[UIDevice currentDevice] systemVersion];

【讨论】:

读者练习:为什么检测设备(而不是功能)总是一个坏主意。【参考方案7】:
UIScreen *MainScreen = [UIScreen mainScreen];
UIScreenMode *ScreenMode = [MainScreen currentMode];
CGSize Size = [ScreenMode size]; // <--- Real screen size

【讨论】:

【参考方案8】:

对于那些只想复制/粘贴如何检测 iphone/iphone_retina/ipad/ipad_retina 的人来说,这是我在阅读此主题后最终所做的。深受 Guntis Treulands 贡献的启发,后者又扩展了 Scott Gustafson 的回答。

- (NSString *) yesButWhichDeviceIsIt     
    BOOL hasRetina = NO;
    if ([UIScreen instancesRespondToSelector:@selector(scale)]) 
        CGFloat scale = [[UIScreen mainScreen] scale];
        if (scale > 1.0) 
            hasRetina = YES;
        
    
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 
        if (hasRetina) 
            return @"iPad retina";
         else 
            return @"iPad";
        
     else 
        if (hasRetina) 
            return @"iPhone retina";
         else 
            return @"iPhone";
                
    

【讨论】:

【参考方案9】:

如果您使用的是 Cocos2d,请尝试以下操作:

[[CCDirector sharedDirector] winSizeInPixels];

它将返回一个CGSize,其属性为widthheight

【讨论】:

【参考方案10】:
+(BOOL)Retina
        return ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))?1:0; 

【讨论】:

正常的 Cocoa 命名习惯要求使用小写首字母命名方法。【参考方案11】:

虽然您已经选择了一个答案,但是在专门处理图像时有一个更简单的方法,所以我也会提到它。

如果您在捆绑包中包含两种尺寸(320x480 和 640x960)的两张图片,并在后一张图片的文件名末尾附加“@2x”,[UIImage imageNamed:] 将自动为旧设备选择较小的图片如果您不使用图像后缀,则为具有视网膜显示屏的设备的 2x。例如:

2 张名为 @"image.png" 和 @"image@2x.png" 的图片都包含在应用程序包中。

然后调用:

[UIImage imageNamed:@"image"];

这也是应用程序图标和加载屏幕的工作方式。

【讨论】:

-1: 你没看文章开头吗...?引用,“在我的应用程序中,我正在从网络上下载一些图像

以上是关于在 iPhone SDK 中检测视网膜屏幕/iPhone 4的主要内容,如果未能解决你的问题,请参考以下文章

在我的屏幕上安装 iPhone 5 模拟器?

苹果设备数据标准(自己总结,持续完善)

如何处理 iPhone 5 视网膜显示检查?

iPhone 模拟器不显示 iphone 5 兼容图像

iPhone iOS 如何以不同的分辨率或比例渲染屏幕截图?

iPhone 5.1 模拟器(视网膜)看起来好大