在“ViewController.swift”中我正在创建这个回调:
func callback(cf:CFNotificationCenter!,
ump:UnsafeMutablePointer<Void>,
cfs:CFString!,
up:UnsafePointer<Void>,
cfd:CFDictionary!) -> Void {
}
使用这个观察者:
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
nil,
self.callback,
"myMESSage",
nil,
CFNotificationSuspensionBehavior.DeliverImmediately)
此编译器错误的结果:
"A C function pointer can only be formed from a reference to a 'func' or a literal closure"
最佳答案
回调是一个指向 C 函数的指针,在 Swift 中你可以通过 只有一个全局函数或一个闭包(不捕获任何状态), 但不是实例方法。
所以这确实有效:
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
nil,
{ (_, observer, name, _, _) in
print("received notification: \(name)")
},
"myMessage",
nil,
.DeliverImmediately)
但由于闭包无法捕获上下文,您无法直接引用 self
及其属性和实例方法。
例如,您不能添加
self.label.stringValue = "got it"
// error: a C function pointer cannot be formed from a closure that captures context
在通知到达时在闭包内更新 UI。
有一个解决方案,但由于以下原因有点复杂
Swift 的严格类型系统。
类似于 Swift 2 - UnsafeMutablePointer<Void> to object ,您可以将指针转换为
self
为空指针,将其作为 observer
参数传递
注册,并将其转换回一个对象指针
回调。
class YourClass {
func callback(name : String) {
print("received notification: \(name)")
}
func registerObserver() {
// Void pointer to `self`:
let observer = UnsafePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
observer,
{ (_, observer, name, _, _) -> Void in
// Extract pointer to `self` from void pointer:
let mySelf = Unmanaged<YourClass>.fromOpaque(
COpaquePointer(observer)).takeUnretainedValue()
// Call instance method:
mySelf.callback(name as String)
},
"myMessage",
nil,
.DeliverImmediately)
}
// ...
}
闭包充当实例方法的“蹦床”。
指针是一个未保留的引用,因此你必须确保 在对象被释放之前移除观察者。
Swift 3 更新:
class YourClass {
func callback(_ name : String) {
print("received notification: \(name)")
}
func registerObserver() {
// Void pointer to `self`:
let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
observer,
{ (_, observer, name, _, _) -> Void in
if let observer = observer, let name = name {
// Extract pointer to `self` from void pointer:
let mySelf = Unmanaged<YourClass>.fromOpaque(observer).takeUnretainedValue()
// Call instance method:
mySelf.callback(name.rawValue as String)
}
},
"myMessage" as CFString,
nil,
.deliverImmediately)
}
// ...
}
另见 How to cast self to UnsafeMutablePointer<Void> type in swift了解更多信息 关于对象指针和 C 指针之间的“桥接”。
关于swift - 如何将实例方法用作仅采用 func 或文字闭包的函数的回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33260808/