2010-08-17 140 views
220

iOS SDK是否提供了一种简单的方法来检查currentDevice是否具有高分辨率显示(视网膜)?检测视网膜显示

我发现现在做到这一点的最好办法是:

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00) { 
     // RETINA DISPLAY 
    } 
+0

出于好奇 - 你在做什么,当你发现其他的显示器不是显示较大的版本的艺术作品? – mbehan 2010-08-17 15:35:17

+4

可能重复的[如何区分iphone4和iphone 3](http://stackoverflow.com/questions/3294100/how-to-differentiate-between-iphone4-and-iphone-3) – 2010-08-17 17:09:45

+0

@mbehan:我有一个TTImageView(请参阅Three20框架),我想给出图像的高分辨率URL。 – 2010-08-18 10:05:26

回答

293

为了可靠地检测在所有iOS设备的Retina显示屏,你需要检查设备运行iOS4的+,如果[UIScreen mainScreen].scale属性等于2.0。如果scale属性存在,则不能假定设备正在运行iOS4 +,因为iPad 3.2也包含此属性。

在运行iOS3.2的iPad上,缩放将在1x模式下返回1.0,在2x模式下返回2.0 - 即使我们知道设备不包含Retina显示屏。 Apple在iOS4.2中为iPad改变了这种行为:它在1x和2x模式下均返回1.0。你可以在模拟器中自己测试一下。

我测试存在于iOS4.x但不iOS3.2在主屏幕上的-displayLinkWithTarget:selector:方法,然后检查屏幕的规模:

if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && 
    ([UIScreen mainScreen].scale == 2.0)) { 
    // Retina display 
} else { 
    // non-Retina display 
} 
+0

你说“苹果公司改变了iOS4.2的iPad的行为”,暗示在iOS4.1中,上述代码将以2x模式运行iPhone应用程序的iPad返回“is Retina”。我错了吗? – makdad 2012-03-11 12:26:45

+9

从来没有一个4.1的iPad。只有3.2,然后是4.2。 – Jonny 2012-04-02 18:26:33

+11

这个调用有点贵,所以我会在应用程序启动时用它初始化一个BOOL,并在应用程序中使用它。 – n13 2012-05-20 14:22:54

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

为什么'?1:0'?这不仅仅是重申已经在表达式的布尔部分中计算出的内容吗? – d11wtq 2013-02-04 04:58:10

6

这个片段...

int d = 0; // standard display 
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0) { 
    d = 1; // is retina display 
} 

if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 
    d += 2; 
} 

将返回... 0的标准分辨率的iPhone/iPod touch上, 1视网膜iPhone, 2标准分辨率iPad, 3用于视网膜iPad。

78

@ sickp的答案是正确的。只是为了让事情变得更容易,添加此行到您的Shared.pch文件:任何文件,你可以做

#define IS_RETINA ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale >= 2.0)) 

然后:

if(IS_RETINA) 
{ 
    // etc.. 
} 
+0

非常好的结构化答案。谢谢 – 2014-10-16 09:25:27

+0

这在模拟器上不起作用。是因为respondsToSelector吗?模拟器不响应选择器? – arniotaki 2015-02-19 08:27:52

+2

太棒了!但是,如果你想考虑iPhone 6 Plus,你应该检查scale> = 2.0。 – 2015-04-15 01:25:32

5

它,总觉得有点不可靠,比较浮点平等的价值观。 我宁愿去为任何

[UIScreen mainScreen].scale > 1.0; 

[UIScreen mainScreen].scale < 2.0; 
+5

比较两个浮点值的相等“感觉不好”,因为它们在计算之后可能与整数值略有不同。但与< or >相比,在这些情况下也是如此狡猾。然而,在这种情况下,根本不可能有任何规模不完全是1.0或2.0,因为它是硬件定义的。 – fishinear 2013-03-22 17:19:34

+0

@fishinear建议,最好使用'isRetina = [UIScreen mainScreen] .scale> 1.95'。当@ 4x出现时,这也会有弹性的好处:) – 2013-08-06 15:44:07

+0

我强烈反对。在不需要时执行此操作会使代码不易读。关于未来证明的观点可能有其合理性,但我怀疑我们很快就会有@ 4x的屏幕(如果有的话)。 – 2013-08-16 17:03:07

1

刚刚从@sickp答案结合起来,从@ N13这样的评论我做这个成UIScreen范畴,这似乎很好地工作。该检查在您第一次打电话时完成,然后保存以供稍后调用。

@interface UIScreen (RetinaCheck) 
+ (BOOL)retinaScreen; 
@end 

static BOOL isRetinaScreen = NO; 
static BOOL didRetinaCheck = NO; 

@implementation UIScreen (RetinaCheck) 
+ (BOOL)retinaScreen 
{ 
    if (!didRetinaCheck) { 
     isRetinaScreen = ([[self mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && 
          ([self mainScreen].scale == 2.0)); 
     didRetinaCheck = YES; 
    } 
    return isRetinaScreen; 
} 
@end 

可能对某人有用。

+0

感谢您的缓存代码。我唯一的建议是使这个'(Util)'而不是'(RetinaCheck)'......也许不那么清楚,但它适用于其他用途。 另外我会命名方法'isRetinaDisplay'或以'is'开头的东西,但也许我从来没有理解Obj-C的指导原则。 另外,我是'> 1.0的粉丝,但谁知道什么会有意义的前进。 – 2013-11-13 20:28:13

2

这是马特MC的回答上面的一段。只是UIScreen的一个类别。

#import "UIScreen+Util.h" 

@implementation UIScreen (Util) 

+ (BOOL) isRetinaDisplay { 
    static BOOL retina = NO; 
    static BOOL alreadyChecked = NO; 
    if (!alreadyChecked) { 
     UIScreen *mainScreen = self.mainScreen; 
     if (mainScreen) { 
      retina = mainScreen.scale > 1.0; 
      alreadyChecked = YES; 
     } 
    } 
    return retina; 
} 

@end 
+1

我怀疑'alreadyChecked'的缓存是无偿的,但没关系。 – 2013-11-28 20:55:48

+0

多线程情况怎么样? – 2014-04-22 12:18:43

+0

@NikolayShubenkov这就是为什么我已经设置了最后检查。在最坏的情况下,你运行代码来检查额外的一两次。 – 2014-04-23 01:06:20

0

尝试高于此

if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && 
    ([UIScreen mainScreen].scale == 2.0)) 
{ 
    // Retina display 
    NSLog(@"---------------Retina display"); 
} else { 
    // non-Retina display 
    NSLog(@"---------------non-Retina display"); 
} 
1
// .h 
UIKIT_EXTERN bool isRetinaDisplay(); 

// .m 
bool isRetinaDisplay() 
{ 
    static bool flag; 
#ifdef __BLOCKS__ 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     if([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
     { 
      flag = [[UIScreen mainScreen] scale] > 1.0; 
     } 
     else 
     { 
      flag = false; 
     } 
    }); 
#else 
    static bool onceToken; 
    if(onceToken == false) 
    { 
     onceToken = true; 
     if([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) 
     { 
      flag = [[UIScreen mainScreen] scale] > 1.0; 
     } 
     else 
     { 
      flag = false; 
     } 
    } 
#endif 
    return flag; 
} 
+0

我认为最好的解决方案。 – 2014-04-22 12:20:01

2

的答案夫特版本,> = 2.0规模所以它包括iPhone 6+和其他未来的设备与规模比-视网膜更高:

if UIScreen.mainScreen().respondsToSelector(Selector("scale")) && UIScreen.mainScreen().scale >= 2.0 { 
    // code executed only on Retina device 
} 
5

这里是一个方便快捷的扩展:

extension UIScreen { 
public func isRetina() -> Bool { 
    return screenScale() >= 2.0 
} 

public func isRetinaHD() -> Bool { 
    return screenScale() >= 3.0 
} 

private func screenScale() -> CGFloat? { 
    if UIScreen.mainScreen().respondsToSelector(Selector("scale")) { 
     return UIScreen.mainScreen().scale 
    } 
    return nil 
    } 
} 

用法:primulaveris年代为最常见的使用情况简单

if UIScreen.mainScreen().isRetina() { 
// your code 
     } 
0

改良版。我在迅速2.2,但它应该没关系。

extension UIScreen { 
    static var isRetina: Bool { 
     return screenScale >= 2.0 
    } 

    static var isRetinaHD: Bool { 
     return screenScale >= 3.0 
    } 

    static var screenScale:CGFloat { 
     return UIScreen.mainScreen().scale 
    } 
} 

然后只需用他们喜欢这个

print(UIScreen.isRetina) 
print(UIScreen.isRetinaHD) 
print(UIScreen.screenScale) 
0

这为我工作

if((UIScreen .mainScreen().scale) < 2.0) 
{ 
    NSLog("no retina"); 
} 
else 
{ 
    NSLog("retina"); 
}