回调函数是指向C函数的指针,在Swift中,您只能传递全局函数或不捕获任何状态的闭包(closure),而不能传递实例方法。
因此,下面的代码可行:
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
当通知到达时,在闭包内更新界面是有解决方案的。
但是由于Swift的严格类型系统,这个解决方案有点复杂。
与Swift 2 - UnsafeMutablePointer<Void> to object类似,
你可以将self
转换为一个void指针,将其作为observer
参数传递给注册函数,并在回调函数中将其转换回对象指针。
class YourClass {
func callback(name : String) {
print("received notification: \(name)")
}
func registerObserver() {
let observer = UnsafePointer<Void>(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
observer,
{ (_, observer, name, _, _) -> Void in
let mySelf = Unmanaged<YourClass>.fromOpaque(
COpaquePointer(observer)).takeUnretainedValue()
mySelf.callback(name as String)
},
"myMessage",
nil,
.DeliverImmediately)
}
}
闭包作为实例方法的“跳板”。
该指针是非持有引用,因此必须确保在对象被释放之前移除观察器。
Swift 3更新:
class YourClass {
func callback(_ name : String) {
print("received notification: \(name)")
}
func registerObserver() {
let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
observer,
{ (_, observer, name, _, _) -> Void in
if let observer = observer, let name = name {
let mySelf = Unmanaged<YourClass>.fromOpaque(observer).takeUnretainedValue()
mySelf.callback(name.rawValue as String)
}
},
"myMessage" as CFString,
nil,
.deliverImmediately)
}
}
另请参见
如何在Swift中将self强制转换为UnsafeMutablePointer<Void>类型,以了解有关对象指针和C指针之间的“桥接”的更多信息。