問題是IOPowerSourceCallbackType
是一個C函數。
根據蘋果的文檔,這些功能都可以關閉:
C函數指針被導入到斯威夫特與C函數指針調用約定封閉
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)
}
}
UPDATE
要讓它與循環設置的實例進行交互,必須通過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 point的相關文章ers可以在這裏找到:
http://nshint.io/blog/2015/10/10/working-with-cfunction-pointers-in-swift/
只是你知道;我爲我的答案增加了一個更廣泛的例子 –