问题在于这IOPowerSourceCallbackType
是一个C 函数。
根据 Apple 的文档,这些函数可作为闭包使用:
C 函数指针作为具有 C 函数指针调用约定的闭包导入 Swift
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-ID148
所以最简单的方法是使用闭包:
IOPSNotificationCreateRunLoopSource({ (context: UnsafeMutableRawPointer?) in
debugPrint("Power source changed")
}, &context)
第二种选择是使用顶级函数:
func powerSourceChanged(arg: UnsafeMutableRawPointer?) {
debugPrint("Power source changed")
}
IOPSNotificationCreateRunLoopSource(powerSourceChanged, &context)
作为参考,我如何使用它的完整实现:
class WindowController: NSWindowController {
static var context = 0
override func windowDidLoad() {
super.windowDidLoad()
let loop: CFRunLoopSource = IOPSNotificationCreateRunLoopSource({ (context: UnsafeMutableRawPointer?) in
debugPrint("Power source changed")
}, &WindowController.context).takeRetainedValue() as CFRunLoopSource
CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode)
}
}
更新
要让它与设置循环的实例交互,您必须self
作为上下文传递,但self
不是指针。
当您尝试通过self
在指针前面加上&
( &self
) 来作为指针传递时,您会得到一个self
不可变的错误。
要将其转换为不透明指针,您可以使用Unmanaged
该类:
let opaque = Unmanaged.passRetained(self).toOpaque()
然后可以用作UnsafeMutableRawPointer
:
let context = UnsafeMutableRawPointer(opaque)
我们可以使用什么作为IOPSNotificationCreateRunLoopSource
.
然后在回调中,通过Unmanaged
再次使用该类,我们可以将此指针解析回其初始实例:
let opaque = Unmanaged<WindowController>.fromOpaque(context!)
let _self = opaque.takeRetainedValue()
完整示例:
func PowerSourceChanged(context: UnsafeMutableRawPointer?) {
let opaque = Unmanaged<WindowController>.fromOpaque(context!)
let _self = opaque.takeRetainedValue()
_self.powerSourceChanged()
}
class WindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
let opaque = Unmanaged.passRetained(self).toOpaque()
let context = UnsafeMutableRawPointer(opaque)
let loop: CFRunLoopSource = IOPSNotificationCreateRunLoopSource(
PowerSourceChanged,
context
).takeRetainedValue() as CFRunLoopSource
CFRunLoopAddSource(CFRunLoopGetCurrent(), loop, CFRunLoopMode.defaultMode)
}
func powerSourceChanged() {
debugLog("Power source changed")
}
}
奖金
一篇关于 CFunction 指针的相关文章