2 回答

TA貢獻(xiàn)2080條經(jīng)驗 獲得超4個贊
回調(diào)是指向C函數(shù)的指針,在Swift中,您只能傳遞全局函數(shù)或閉包(不捕獲任何狀態(tài)),但不能傳遞實例方法。
所以這確實有效:
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
在閉包內(nèi)部,在通知到達(dá)時更新UI。
有一個解決方案,但由于Swift嚴(yán)格的類型系統(tǒng),它有點復(fù)雜。與Swift 2 - UnsafeMutablePointer <Void>中的對象類似,您可以將指針轉(zhuǎn)換 self
為void指針,將其作為observer
參數(shù)傳遞給注冊,并將其轉(zhuǎn)換回回調(diào)中的對象指針。
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) } // ...}
閉包充當(dāng)實例方法的“蹦床”。
指針是未保留的引用,因此必須確保在取消分配對象之前刪除觀察者。
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) } // ...}
有關(guān)對象指針和C指針之間“橋接”的更多信息,另請參見如何將self轉(zhuǎn)換為UnsafeMutablePointer <Void>鍵入swift。

TA貢獻(xiàn)1875條經(jīng)驗 獲得超5個贊
在我的例子中,我想從我的閉包中調(diào)用的函數(shù)是在AppDelegate中。所以我能夠使用委托從閉包中調(diào)用函數(shù)而不使用self。這是否是一個好主意是具有更多經(jīng)驗的人必須評論的東西。
self.pingSocket = CFSocketCreate(kCFAllocatorDefault, AF_INET, SOCK_DGRAM, IPPROTO_ICMP,CFSocketCallBackType.dataCallBack.rawValue, {socket, type, address, data, info in //type is CFSocketCallBackType guard let socket = socket, let address = address, let data = data, let info = info else { return }// stuff deleted, including use of C pointers let appDelegate = NSApplication.shared.delegate as! AppDelegate appDelegate.receivedPing(ip: sourceIP, sequence: sequence, id: id) //} return }, &context)extension AppDelegate: ReceivedPingDelegate { func receivedPing(ip: UInt32, sequence: UInt16, id: UInt16) { // stuff deleted }}protocol ReceivedPingDelegate: class { func receivedPing(ip: UInt32, sequence: UInt16, id: UInt16)}
- 2 回答
- 0 關(guān)注
- 498 瀏覽
添加回答
舉報