Skip to content

Instantly share code, notes, and snippets.

@BomberFish
Last active March 13, 2024 14:53
Show Gist options
  • Save BomberFish/27e5231c9e9e4e0de2958a3a48ba14c3 to your computer and use it in GitHub Desktop.
Save BomberFish/27e5231c9e9e4e0de2958a3a48ba14c3 to your computer and use it in GitHub Desktop.
Programmatically get advanced battery information on Apple devices
/// Rewrite of https://gist.github.com/leminlimez/ed3e3ee3a287c503c5b834acdc0dfcdc in Swift (the superior language)
/// NOTE: To use IOKit, you need to create a bridging header with the following contents: `#include <IOKit/IOKitLib.h>`
/// This requires you to have the (private) `systemgroup.com.apple.powerlog` entitlement.
func getBatteryInfo() throws -> [String:Any] {
var service: io_service_t? // Battery IOService
service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("AppleSmartBattery")) // iPhone 11+
if service == nil {
service = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOPMPowerSource")) // Earlier iPhones
}
if let service {
defer {IOObjectRelease(service)} // Release IOService on function exit
var prop: Unmanaged<CFMutableDictionary>?
IORegistryEntryCreateCFProperties(service, &prop, nil, 0) // Get properties
if let prop,
let dict = prop.takeUnretainedValue() as NSDictionary as? [String:Any] { // shadow typecast dark voodoo magic
return dict
} else {
throw "Could not get battery information." // Either could not get properties or typecast them (take your pick ¯\_(ツ)_/¯)
}
} else {
throw "Could not communicate with IOKit." // Could not get service
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment