Battery level with IOPSCopyPowerSourcesList

I want to get battery level, estimated remaining time, battery health...etc via IOPSCopyPowerSourcesList

Not sure how

I'm not experienced with pointers...

    func updateBatteryView() {
        let battery = IOPSCopyPowerSourcesInfo().takeRetainedValue()
        let info = IOPSCopyPowerSourcesList(battery).takeRetainedValue()
        // Now what?
    }

These APIs have not been audited for nullability, so they all return unmanaged values that are also implicitly unwrapped optionals. To call them safely you must:

  • Check for nil, otherwise if they fail you’l trap.

  • Call either takeRetainedValue() or takeUnretainedValue() depending on whether the document say you are expected to release the value or not.

So, you need code like that shown at the end of this post. Some notes:

  • The docs for IOPSCopyPowerSourcesInfo and IOPSCopyPowerSourcesList say to release the value, hence the takeRetainedValue().

  • The docs for IOPSGetPowerSourceDescription say not to release the value, hence takeUnretainedValue().

  • The keys for the dictionary are defined in <IOKit/ps/IOPSKeys.h>.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"


import Foundation
import IOKit.ps

func test() {
    guard
        let psi = IOPSCopyPowerSourcesInfo()?.takeRetainedValue(),
        let cf = IOPSCopyPowerSourcesList(psi)?.takeRetainedValue()
    else { … handle error … }
    let psl = cf as [CFTypeRef]
    for ps in psl {
        guard let cfd = IOPSGetPowerSourceDescription(psi, ps)?.takeUnretainedValue() else { … handle error … }
        let d = cfd as! [String: Any]
        guard
            let psID = d[kIOPSPowerSourceIDKey] as? Int,
            let psTypeStr = d[kIOPSTypeKey] as? String,
            let psType = PowerSourceType(string: psTypeStr)
        else { … handle error … }
        print(psID, psType)
    }
}

enum PowerSourceType {
    case ups
    case internalBattery
}

extension PowerSourceType {
    init?(string: String) {
        switch string {
        case kIOPSUPSType: self = .ups
        case kIOPSInternalBatteryType: self = .internalBattery
        default: return nil
        }
    }
}
Battery level with IOPSCopyPowerSourcesList
 
 
Q