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

23
在我的应用程序中,我从网络上下载一些图像(确切地说是从我的服务器),为了节省一些带宽和手机内存,我提供两种分辨率:480x320适用于“旧”iPhone系列,960x640适用于带视网膜显示的iPhone 4。现在我需要能够在应用程序运行时检测设备是否支持视网膜屏幕。我该如何做呢?
我一直在考虑使用下面的代码片段,它会返回一个特定的设备标识符,例如“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];

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

11个回答

32

我在官方的苹果开发者论坛上看到了一些内容,这个问题已经被广泛讨论过了。我认为最好的方法是使用UIScreenscale属性。虽然只有在iOS 4及更高版本中可用,但它会告诉你所需的一切,并且很可能在将来扮演更重要的角色(已经注意到iPad的屏幕分辨率为1024x768,恰好是480x320的32/15倍?)。

UIScreen.mainScreen.scale

如果您有其他想法,请随意发表 :)


2
是的,请使用这个,永远不要尝试查询您正在运行的设备,否则只会带来痛苦。 - Joshua Weinberg
这是正确的方法,因为您不想为iPhone 4编写条件代码,而是为具有不同比例/分辨率的显示器编写。谁知道iPod何时会得到视网膜处理。 - Felix Lamouroux
1
@Felix:希望在下一个更新中,预计在一月份发布。如果我们的代码可以在没有任何调整的情况下自动支持它,那不是非常棒吗?因此,[UIScreen scale] 是最佳方法。 - Dan Ray

23

以下是一些代码,可用于同时在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以2倍的模式启动,则此代码也会返回“true”,这可能是您想要的,也可能不是。 - Matt Rix
2
iPad的“iPhone模拟器”上的2倍问题有解决方法吗? - joelsand

13

关于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
               }
         }
    }

5

我可以通过以下方式获取真实的屏幕尺寸(以像素为单位):

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

3
- (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;
}

1
对于那些只想复制/粘贴如何检测 iPhone/iPhone_retina/iPad/iPad_retina 的人,这是我在阅读本主题后最终采取的方法。这个方法受到 Guntis Treulands 的启发,他又扩展了 Scott Gustafsons 的答案。
- (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";
        }        
    }
}

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

1

跟随Robin的答案。另外需要注意的是,如果你确实需要检查设备名称,只需使用UIDevice上的方法即可。

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

1
读者练习:为什么检测设备(而不是能力)总是一个坏主意。 - Stephen Eilert

0
+(BOOL)Retina{
        return ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))?1:0; }

2
通常的Cocoa命名惯例是使用小写字母作为方法名称的首字母。 - Monolo

0
如果您正在使用Cocos2d,请尝试以下操作:
[[CCDirector sharedDirector] winSizeInPixels];
它将返回一个CGSize,其中包含width和height属性。

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