Mac OS X:检测Retina显示屏的最佳方法是什么?

19

给定一个在 Mac OS X 10.7 及以上版本上运行的 Cocoa 应用:

如何在运行时最好地检查你的应用当前是否正在运行于连接有至少一个 Retina 显示器的 Mac 上?

如果检查这种情况只是很错误的想法,我完全欢迎一个合理的解释为什么(如果这些答案很好,我会点赞的)。

但我仍然想知道:)

看起来你可以只针对新款 Mac Book Pro 的 "Retina" 硬件进行检查(目前唯一具有 Retina 显示器的 Mac),但我更喜欢一种更通用/未来可靠的检查方式。

理想情况下,我想知道如何检测 Retina 显示器,而不是当前恰巧带有 Retina 显示器的特定 Mac 型号。

3个回答

33

如果你确实需要这样做,可以查看 -[NSScreen backingScaleFactor]。但是,这似乎是错误的,至少在不知道更多信息的情况下。

虽然目前只有一台带Retina显示屏的Mac电脑,但可能会有支持Retina的独立显示器(可以在运行时连接/断开),并且您可能能够将内置的Retina显示器配置为1x模式。因此,“是否连接了Retina显示器”的答案可能随时发生变化。

相反,您可能想知道是否应该使用 -convert*ToBacking:方法或-[NSWindow backingScaleFactor]方法以给定比例绘制内容。要获取更多详细信息,请观看WWDC 2012会议视频“高分辨率OS X的高级技巧和技巧”(希望在接下来的几周内发布)。


4
+1,同时 OP 应该阅读 OS X 高分辨率指南 - Ken Thomases
3
现在这样做并不是错误的想法。网站现在绝对需要这样做,以便为iPad和iPhone提供正确的资源,那么为什么应用程序会有所不同呢?当然,在简单的资产交换情况下(即@2x情况),自行检查而不是让操作系统来执行是错误的想法。 :) - God of Biscuits
2
一个网络浏览器可能需要下载2倍大小的图片,但仅当浏览器窗口在2倍分辨率的显示器上时才需要...这可能会因为上述原因随时发生变化。 - tjw
1
并非所有的UIKit/AppKit类都支持@2x资源交换,以您的用户期望的方式(NSImageView就是一个例子)。不要太过谨慎,因为打破各种开发“禁忌”是有“正确”的原因的。 - ctpenrose
1
+1 但请不要建议人们使用 -[NSScreen backingScaleFactor],我经常看到 [[NSScreen mainScreen] backingScaleFactor] 这是非常错误的!我写了一篇关于此的文章 NSView,NSCell,CALayer Draw for Retina Display - Micha Mazaheri
显示剩余2条评论

9

我遇到一个需要检测任何屏幕是否高分辨率的情况,以下是解决方案:

float displayScale = 1;
    if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]) {
        NSArray *screens = [NSScreen screens];
        NSUInteger screenCount = screens.count
        for (int i = 0; i < screenCount; i++) {
            float s = [screens[i] backingScaleFactor];
            if (s > displayScale)
                displayScale = s;
        }
    }

4
你是否知道快速迭代的写法,例如 for (NSScreen *screen in [NSScreen screens])?这样可以大大减少代码敲击量(而且在运行时也更快)。 - DarkDust
是的,这个可以工作!点赞! float displayScale = 1.0; if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]) { for (NSScreen *screen in [NSScreen screens]) { float s = [screen backingScaleFactor]; if (s > displayScale) displayScale = s; } } NSLog(@"displayScale=%f",displayScale); float x0 = displayScale * self.frame.origin.x; float y0 = displayScale * self.frame.origin.y; float w0 = displayScale * self.frame.size.width; float h0 = displayScale * self.frame.size.height; NSLog(@"x=%f;y=%f;w=%f'h=%f",x0,y0,w0,h0); - Jiulong Zhao

5

2
backingScaleFactor不是一个类方法。因此,它应该是[[NSScreen mainScreen] backingScaleFactor]或者[NSScreen screens]之一的。 - erkanyildiz
请忘记 -[NSScreen backingScaleFactor],正确的方法是根据窗口的比例因子调整您的绘图代码。系统负责确定适用于给定窗口的比例因子。 - Micha Mazaheri
2
有时候你在绘图的时候并不需要这个。就像我的情况一样,我正在从多个屏幕上截屏,然后你必须计算准确的像素位置。-[NSScreen backingScaleFactor] 是正确的方法。 - Git.Coach
@ThomasJohannesmeyer 我同意!但这只是一些罕见的情况,大多数应用程序只需要关心它们的窗口,而不是屏幕。 - Micha Mazaheri

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