17

我想知道 Mac OSX 下的物理屏幕尺寸。但是NSDeviceResolution总是报错值(72),所以分辨率/dpi的计算结果是错误的。

在“About This Mac”里面,有一个 Mac 型号字符串,我的是“15-inch, Early 2011”。所以我想知道是否有办法(可能在 obj-c 中)读取该字符串,然后我可以将其用作物理屏幕尺寸。

任何帮助表示赞赏。

4

2 回答 2

26

您可以使用CGDisplayScreenSize以毫米为单位获取屏幕的物理尺寸。鉴于您已经知道分辨率,您可以从中计算 DPI。

所以例如

NSScreen *screen = [NSScreen mainScreen];
NSDictionary *description = [screen deviceDescription];
NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
CGSize displayPhysicalSize = CGDisplayScreenSize(
            [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);

NSLog(@"DPI is %0.2f", 
         (displayPixelSize.width / displayPhysicalSize.width) * 25.4f); 
         // there being 25.4 mm in an inch

@"NSScreenNumber"东西看起来很狡猾,但却CGDirectDisplayIDNSScreen.

于 2012-09-25T19:29:42.063 回答
5

上面汤米的回答非常好——我已经将它移植到了 Swift(供我自己使用)并在此处发布作为参考,但汤米的回答应该被认为是规范的。

import Cocoa

public extension NSScreen {
    var unitsPerInch: CGSize {
        let millimetersPerInch:CGFloat = 25.4
        let screenDescription = deviceDescription
        if let displayUnitSize = (screenDescription[NSDeviceDescriptionKey.size] as? NSValue)?.sizeValue,
            let screenNumber = (screenDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber)?.uint32Value {
            let displayPhysicalSize = CGDisplayScreenSize(screenNumber)
            return CGSize(width: millimetersPerInch * displayUnitSize.width / displayPhysicalSize.width,
                          height: millimetersPerInch * displayUnitSize.height / displayPhysicalSize.height)
        } else {
            return CGSize(width: 72.0, height: 72.0) // this is the same as what CoreGraphics assumes if no EDID data is available from the display device — https://developer.apple.com/documentation/coregraphics/1456599-cgdisplayscreensize?language=objc
        }
    }
}

if let screen = NSScreen.main {
    print("main screen units per inch \(screen.unitsPerInch)")
}

请注意,返回的值实际上是“每英寸点数”(但不是所有定义;见下文),几乎不是“每英寸像素数”——现代 Mac 的每点像素数取决于当前系统偏好设置中的“分辨率”设置和设备的固有分辨率(Retina 显示器有更多的像素)。

返回值的了解是,如果你用类似的代码画一条线

CGRect(origin: .zero, size: CGSize(width: 10, height: 1)).fill()

如果你用一把非常精确的尺子在屏幕上测量它,这条线将是1 / pointsPerInch.height英寸高和英寸宽。1 / pointsPerInch.width

(长期以来,图形框架将“点”定义为“现实世界中的 1/72 英寸”以及“无论1 x 1 单位的框的宽度或高度最终在当前以当前分辨率进行监控 — 通常是相互冲突的两个定义。)

所以对于这段代码,我使用“单位”这个词来表明我们不是在处理 1/72 英寸,也不是 1 个物理像素。

于 2019-04-28T00:09:41.553 回答