Como usar o método de instância como retorno de chamada para a function que leva apenas fechamento func ou literal

Em “ViewController.swift” estou criando este retorno de chamada:

func callback(cf:CFNotificationCenter!, ump:UnsafeMutablePointer, cfs:CFString!, up:UnsafePointer, cfd:CFDictionary!) -> Void { } 

Usando este observador:

 CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), nil, self.callback, "myMESSage", nil, CFNotificationSuspensionBehavior.DeliverImmediately) 

Resultados neste erro do compilador: “ponteiro de function AC só pode ser formado de uma referência para um ‘func’ ou um fechamento literal”

    O retorno de chamada é um ponteiro para uma function C e, no Swift, é possível transmitir apenas uma function global ou um encerramento (que não captura nenhum estado), mas não um método de instância.

    Então isso funciona:

      CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), nil, { (_, observer, name, _, _) in print("received notification: \(name)") }, "myMessage", nil, .DeliverImmediately) 

    Mas, como o encerramento não pode capturar o contexto, você não possui uma referência direta a self e suas propriedades e methods de instância. Por exemplo, você não pode adicionar

      self.label.stringValue = "got it" // error: a C function pointer cannot be formed from a closure that captures context 

    dentro do fechamento para atualizar a interface do usuário quando uma notificação chegou.

    Há uma solução, mas é um pouco complicada devido ao sistema de tipo estrito da Swift. Da mesma forma que no Swift 2 – UnsafeMutablePointer , você pode converter o ponteiro para self em um void void, passar isso como o parâmetro observer para o registro e convertê-lo de volta para um ponteiro de object no callback.

     class YourClass { func callback(name : String) { print("received notification: \(name)") } func registerObserver() { // Void pointer to `self`: let observer = UnsafePointer(Unmanaged.passUnretained(self).toOpaque()) CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, { (_, observer, name, _, _) -> Void in // Extract pointer to `self` from void pointer: let mySelf = Unmanaged.fromOpaque( COpaquePointer(observer)).takeUnretainedValue() // Call instance method: mySelf.callback(name as String) }, "myMessage", nil, .DeliverImmediately) } // ... } 

    O fechamento funciona como um “trampolim” para o método da instância.

    O ponteiro é uma referência não retida, portanto, você deve garantir que o observador seja removido antes que o object seja desalocado.


    Atualização para o 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.fromOpaque(observer).takeUnretainedValue() // Call instance method: mySelf.callback(name.rawValue as String) } }, "myMessage" as CFString, nil, .deliverImmediately) } // ... } 

    Veja também How to cast self para UnsafeMutablePointer digite swift para mais informações sobre o “bridging” entre pointers de object e pointers C.