macosswiftcocoabatterybatterylevel

Fetch the battery status of my MacBook with Swift


I want to setup a Playground to fetch the battery status of my macbook.

I have already tried the following:

import Cocoa
import IOKit
import Foundation

var blob = IOPSCopyPowerSourcesInfo()

I am currently receiving an error as below

Use of unresolved identifier 'IOPSCopyPowerSourcesInfo'


Solution

  • It doesn't work in a Playground, but it works in a real app.

    I couldn't access the IOPowerSources.h header file with Swift and import IOKit only, though: I had to make a bridge to Objective-C.

    Here's my solution:

    1. Add IOKit.framework to your project (click + in Linked Frameworks and Libraries)

    2. Create a new empty .m file, whatever its name. Xcode will then ask if it should make a "bridging header". Say YES.

    3. Ignore the .m file. In the new YOURAPPNAME-Bridging-Header.h file that Xcode just created, add the line #import <IOKit/ps/IOPowerSources.h> (and don't add import IOKit in your Swift file)

    4. You can now access most of the IOPowerSources functions.

    Example:

    func getBatteryStatus() -> String {
        let timeRemaining: CFTimeInterval = IOPSGetTimeRemainingEstimate()
        if timeRemaining == kIOPSTimeRemainingUnlimited {
            return "Plugged"
        } else if timeRemaining == kIOPSTimeRemainingUnknown {
            return "Recently unplugged"
        } else {
            let minutes = timeRemaining / 60
            return "Time remaining: \(minutes) minutes"
        }
    }
    
    let batteryStatus = getBatteryStatus()
    print(batteryStatus)
    

    Another example, with IOPSCopyPowerSourcesInfo:

    let blob = IOPSCopyPowerSourcesInfo()
    let list = IOPSCopyPowerSourcesList(blob.takeRetainedValue())
    print(list.takeRetainedValue())
    

    Think to release all retained CFValues (here: blob & list) at the function end with: CFRelease(value) >> here: CFRelease(blob) & CFRelease(list)

    Result:

    (
    {
    "Battery Provides Time Remaining" = 1;
    BatteryHealth = Good;
    Current = 0;
    "Current Capacity" = 98;
    DesignCycleCount = 1000;
    "Hardware Serial Number" = 1X234567XX8XX;
    "Is Charged" = 1;
    "Is Charging" = 0;
    "Is Present" = 1;
    "Max Capacity" = 100;
    Name = "InternalBattery-0";
    "Power Source State" = "AC Power";
    "Time to Empty" = 0;
    "Time to Full Charge" = 0;
    "Transport Type" = Internal;
    Type = InternalBattery;
    }
    )