在“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>(
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指针之间的“桥接”