如何使用实例方法作为只接受func或literal闭包的函数的回调

在“ViewController.swift”中,我正在创建此回调:

函数回调(cf:CFNotificationCenter!,
ump:unsafemeutablepointer<Void>,
cfs:CFString!,
向上:未安全指针<无效>,
cfd:CFDictionary!)->空虚{
}

使用该观察者:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
无
自我回调,
“我的消息”,
无
CFNotificationSuspensionBehavior.立即交付)

导致此编译器错误:

“C函数指针只能由对“func”或文字闭包的引用构成”

回调是指向C函数的指针,在Swift中可以传递
仅全局函数或闭包(不捕获任何状态),
但不是一个实例方法

所以这确实有效:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
无
{({,观察者,姓名,{,})in
打印(“收到的通知:\(名称)”)
},
“我的消息”,
无
.立即交付)

但是,由于闭包无法捕获上下文,因此您没有对self及其属性和实例方法的直接引用。
例如,您不能添加

self.label.stringValue=“明白了”
//错误:无法从捕获上下文的闭包中形成C函数指针

在闭包内部,在通知到达时更新UI

有一个解决方案,但由于
斯威夫特严格的打字系统。
类似于Swift 2-不可女性化指针<无效>要创建对象,可以将指针转换为
self将其作为observer参数传递给空指针
,并将其转换回中的对象指针
回调

给你的班级上课{
func回调(名称:字符串){
打印(“收到的通知:\(名称)”)
}
func registerObserver(){
//指向“self”的无效指针:
let observer=UnsafePointer<Void>(Unmanaged.passUnretained(self.toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
观察者
{({,观察者,姓名,{,})->Void in
//从空指针中提取指向“self”的指针:
让我自己=Unmanaged<YourClass&gt(
COpaquePointer(观察者)).takeUnretainedValue()
//调用实例方法:
回调(名称为字符串)
},
“我的消息”,
无
.立即交付)
}
// ...
}

闭包充当实例方法的“蹦床”

指针是未恢复的引用,因此必须确保
在解除分配对象之前移除观察者


Swift 3的更新:

给你的班级上课{
func回调函数(u名称:String){
打印(“收到的通知:\(名称)”)
}
func registerObserver(){
//指向“self”的无效指针:
let observer=UnsafeRawPointer(Unmanaged.passUnretained(self.toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
观察者
{({,观察者,姓名,{,})->Void in
如果让观察者=观察者,则让名称=名称{
//从空指针中提取指向“self”的指针:
让我自己=Unmanaged<YourClass>.fromovaque(observer).takeUnretainedValue()
//调用实例方法:
callback(name.rawValue作为字符串)
}
},
“myMessage”作为CFString,
无
.立即交付)
}
// ...
}

另请参见如何将自我强制转换为不可女性化指针<无效>键入swift以了解更多信息
关于对象指针和C指针之间的“桥接”

发表评论