I am trying to subscribe to changes in power state on macOS. I discovered there is a way using IOKit, though it is a bit convoluted. I need to import it using #import <IOKit/ps/IOPowerSources.h> in an ObjC Bridging header. Then I get access to the function IOPSNotificationCreateRunLoopSource, which has the signature:
IOPSNotificationCreateRunLoopSource(_ callback: IOPowerSourceCallbackType!, _ context: UnsafeMutablePointer<Void>!) -> Unmanaged<CFRunLoopSource>!
I got some help from the answer in Callback method to Apple run loop, but still doesn't manage to create a function of type IOPowerSourceCallbackType in Swift. What is the missing piece to have this compile?
The issue is that
IOPowerSourceCallbackTypeis a C function.According to Apple's documentation these functions are available as closures:
So the easiest way is to use a closure:
A second option is to use a top-level function:
For reference the complete implementation of how I'm using this:
UPDATE
To let it interact with the instance the loop was setup from, you have to pass
selfas context, howeverselfisn't a pointer.When you try to pass
selfas pointer by prepending it with&(&self), you'll get an error thatselfis immutable.To convert it a to an opaque pointer you can use the
Unmanagedclass:Which then can be used as an
UnsafeMutableRawPointer:What we can use as the context for
IOPSNotificationCreateRunLoopSource.And then in the callback, by using the
Unmanagedclass again, we can resolve this pointer back to its initiating instance:Full example:
Bonus
A related article about CFunction pointers