It’s quite easy to detect if Mac has an illuminated keyboard with ioreg
at the command line:
ioreg -c IOResources -d 3 | grep '"KeyboardBacklight" =' | sed 's/^.*= //g'
But how can I programmatically get this IOKit
boolean property using the latest Swift? I’m looking for some sample code.
I figured out the following with some trial and error:
I have tested this on an MacBook Air (with keyboard backlight) and on an iMac (without keyboard backlight), and it produced the correct result in both cases.
import Foundation
import IOKit
func keyboardHasBacklight() -> Bool {
let port: mach_port_t
if #available(macOS 12.0, *) {
port = kIOMainPortDefault // New name as of macOS 12
} else {
port = kIOMasterPortDefault // Old name up to macOS 11
}
let service = IOServiceGetMatchingService(port, IOServiceMatching(kIOResourcesClass))
guard service != IO_OBJECT_NULL else {
// Could not read IO registry node. You have to decide whether
// to treat this as a fatal error or not.
return false
}
guard let cfProp = IORegistryEntryCreateCFProperty(service, "KeyboardBacklight" as CFString,
kCFAllocatorDefault, 0)?.takeRetainedValue(),
let hasBacklight = cfProp as? Bool
else {
// "KeyboardBacklight" property not present, or not a boolean.
// This happens on Macs without keyboard backlight.
return false
}
// Successfully read boolean "KeyboardBacklight" property:
return hasBacklight
}
As an addendum to Martin’s excellent answer, here are the notes I got from Apple’s Developer Technical Support:
Calling I/O Kit from Swift is somewhat challenging. You have two strategies here:
- You can wrap the I/O Kit API in a Swift-friendly wrapper and then use that to accomplish your task.
- You can just go straight to your task, resulting in lots of ugly low-level Swift.
Pulling random properties out of the I/O Registry is not the best path to long-term binary compatibility. Our general policy here is that we only support properties that have symbolic constants defined in the headers (most notably
IOKitKeys.h
, but there are a bunch of others).KeyboardBacklight
has no symbolic constant and thus isn’t supported.
Make sure you code defensively. This property might go away, change meaning, change its type, and so on. Your code must behave reasonable in all such scenarios.
Please make sure you file an enhancement request for a proper API to get this info, making sure to include a high-level description of your overall goal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With