Как читать размер физического экрана OSX?
Я хотел бы узнать размер физического экрана в Mac OSX. Но NSDeviceResolution
всегда сообщает неправильное значение (72), поэтому результат вычисления разрешения /dpi неверен.
Внутри "Об этом Mac" есть строка модели Mac, моя - "15 дюймов, начало 2011 года". Поэтому мне интересно, должен ли быть способ (возможно, в obj-c), прочитать эту строку, а затем я могу использовать ее в качестве физического размера экрана.
Любая помощь приветствуется.
Ответы
Ответ 1
Вы можете использовать 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"
выглядит изворотливой, но является явным документированным способом получения CGDirectDisplayID
из NSScreen
.
Ответ 2
Ответ Tommys выше превосходен - я перенес его на Swift (для моего собственного использования) и выкладываю это здесь в качестве ссылки, но Tommys следует считать каноническим.
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 имеют количество пикселей на точку, которое зависит от текущего "разрешения". msgstr "Настройка в Системных настройках и собственное разрешение устройства (дисплеи 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 физическом пикселе.