NSNotificationCenter addObserver en Swift

¿Cómo se agrega un observador en Swift al centro de notificaciones predeterminado? Intento portar esta línea de código que envía una notificación cuando cambia el nivel de la batería.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil]; 

Es lo mismo que la API de Objective-C, pero usa la syntax de Swift.

 NSNotificationCenter.defaultCenter().addObserver( self, selector: #selector(batteryLevelChanged), name: UIDeviceBatteryLevelDidChangeNotification, object: nil) 

O en Swift 3:

 NotificationCenter.default.addObserver( self, selector: #selector(self.batteryLevelChanged), name: .UIDeviceBatteryLevelDidChange, object: nil) 

Si su observador no hereda de un objeto Objective-C, debe prefijar su método con @objc para usarlo como selector.

 @objc func batteryLevelChanged(notification: NSNotification){ //do stuff } 

Consulte NSNotificationCenter Class Reference , interactuando con Objective-C APIs

Swift 4.0 y Xcode 9.0+:

Notificación de envío (publicación):

 NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil) 

O

 NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"]) 

Recibir (obtener) notificación:

 NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil) 

Controlador de método de función para la notificación recibida:

 @objc func methodOfReceivedNotification(notification: Notification){ } 

Swift 3.0 y Xcode 8.0+:

Notificación de envío (publicación):

 NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil) 

Recibir (obtener) notificación:

 NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil) 

Manejador de métodos para la notificación recibida:

 func methodOfReceivedNotification(notification: Notification){ //Take Action on Notification } 

Eliminar notificación:

 deinit { NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil) } 

Swift 2.3 y Xcode 7:

Notificación de envío (publicación)

  NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil) 

Recibir (Obtener) Notificación

  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil) 

Manejador de métodos para notificaciones recibidas

 func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 


Para versiones históricas de Xcode …



Notificación de envío (publicación)

 NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil) 

Recibir (Obtener) Notificación

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil) 

Eliminar notificación

 NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil) NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed 

Manejador de métodos para notificaciones recibidas

 func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 

Anota la clase o el método de destino con @objc

 @objc private func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } //Or dynamic private func methodOfReceivedNotification(notification: NSNotification){ //Take Action on Notification } 

Swift 3.0 en Xcode 8

Swift 3.0 ha reemplazado muchas API “stringly-typed” con struct “tipos de envoltura”, como es el caso de NotificationCenter. Las notificaciones ahora se identifican mediante una struct Notfication.Name lugar de mediante String . Consulte la guía Migrating to Swift 3 .

Uso anterior :

 // Define identifier let notificationIdentifier: String = "NotificationIdentifier" // Register to receive notification NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil) // Post a notification NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil) 

Nuevo uso de Swift 3.0:

 // Define identifier let notificationName = Notification.Name("NotificationIdentifier") // Register to receive notification NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil) // Post notification NotificationCenter.default.post(name: notificationName, object: nil) 

Todos los tipos de notificaciones del sistema ahora se definen como constantes estáticas en Notification.Name ; es decir .UIDeviceBatteryLevelDidChange , .UIApplicationDidFinishLaunching , .UITextFieldTextDidChange , etc.

Puede extender Notification.Name con sus propias notificaciones personalizadas para mantenerse coherente con las notificaciones del sistema:

 // Definition: extension Notification.Name { static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName") } // Usage: NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil) 

Una buena forma de hacerlo es usar el addObserver(forName:object:queue:using:) lugar del método addObserver(_:selector:name:object:) que a menudo se utiliza desde el código Objective-C. La ventaja de la primera variante es que no tiene que usar el atributo @objc en su método:

  func batteryLevelChanged(notification: Notification) { // do something useful with this information } let observer = NotificationCenter.default.addObserver( forName: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil, queue: nil, using: batteryLevelChanged) 

e incluso puede usar un cierre en lugar de un método si lo desea:

  let observer = NotificationCenter.default.addObserver( forName: NSNotification.Name.UIDeviceBatteryLevelDidChange, object: nil, queue: nil) { _ in print("🔋") } 

Puede usar el valor devuelto para dejar de escuchar la notificación más tarde:

  NotificationCenter.default.removeObserver(observer) 

Solía ​​haber otra ventaja en el uso de este método, que era que no requiere el uso de cadenas de selectores que el comstackdor no podía verificar estáticamente y, por lo tanto, eran frágiles hasta la ruptura si se cambiaba el nombre del método, pero Swift 2.2 y más adelante incluyen #selector expresiones que corrigen ese problema.

  1. Declarar un nombre de notificación

     extension Notification.Name { static let purchaseDidFinish = Notification.Name("purchaseDidFinish") } 
  2. Puede agregar observador de dos maneras:

    Usando Selector

     NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil) @objc func myFunction(notificaiont: Notification) { print(notificaiont.object ?? "") //myObject print(notificaiont.userInfo ?? "") //[AnyHashable("key"): "Value"] } 

    o usando block

     NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in guard let strongSelf = self else { return } strongSelf.myFunction(notificaiont: notification) } func myFunction(notificaiont: Notification) { print(notificaiont.object ?? "") //myObject print(notificaiont.userInfo ?? "") //[AnyHashable("key"): "Value"] } 
  3. Publica tu notificacion

     NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"]) 

de iOS 9 y OS X 10.11. Ya no es necesario que un observador de NSNotificationCenter se registre a sí mismo al ser desasignado. más información

Para una implementación basada en block , necesitas hacer un baile débil y fuerte si quieres usar self dentro del bloque. más información

Pasar datos usando NSNotificationCenter

También puede pasar datos utilizando NotificationCentre en swift 3.0 y NSNotificationCenter en swift 2.0.

Versión Swift 2.0

¿Pasa información utilizando userInfo, que es un diccionario opcional de tipo [NSObject: AnyObject]?

 let imageDataDict:[String: UIImage] = ["image": image] // Post a notification NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil, userInfo: imageDataDict) // Register to receive notification in your class NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: notificationName, object: nil) // handle notification func showSpinningWheel(notification: NSNotification) { if let image = notification.userInfo?["image"] as? UIImage { // do something with your image } } 

Versión de Swift 3.0

El userInfo ahora toma [AnyHashable: Any]? como argumento, que proporcionamos como un diccionario literal en Swift

 let imageDataDict:[String: UIImage] = ["image": image] // post a notification NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict) // `default` is now a property, not a method call // Register to receive notification in your class NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil) // handle notification func showSpinningWheel(_ notification: NSNotification) { if let image = notification.userInfo?["image"] as? UIImage { // do something with your image } } 

Datos de paso de fuente usando NotificationCentre (swift 3.0) y NSNotificationCenter (swift 2.0)

Puedo hacer uno de los siguientes para usar un selector con éxito, sin anotar nada con @objc:

 NSNotificationCenter.defaultCenter().addObserver(self, selector:"batteryLevelChanged:" as Selector, name:"UIDeviceBatteryLevelDidChangeNotification", object:nil) 

O

 let notificationSelector: Selector = "batteryLevelChanged:" NSNotificationCenter.defaultCenter().addObserver(self, selector: notificationSelector, name:"UIDeviceBatteryLevelDidChangeNotification", object:nil) 

Mi versión xcrun muestra Swift 1.2, y esto funciona en Xcode 6.4 y Xcode 7 beta 2 (que pensé que usaría Swift 2.0):

 $xcrun swift --version Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53) 

En swift 2.2 – XCode 7.3, usamos #selector para NSNotificationCenter

  NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil) 

También debemos eliminar la notificación.

Ex.

 deinit { NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil) } 

En swift 3, Xcode 8.2: – comprobación del nivel de estado de la batería

 //Add observer NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil) //Fired when battery level changes func batteryStateDidChange(notification: NSNotification){ //perform manipulation here } 

NSNotificationCenter agrega syntax de observador en Swift 4.0 para iOS 11

  NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 

Esto es para el tipo de nombre de notificación keyboardWillShow. Se puede seleccionar otro tipo de la opción disponible

el Selector es del tipo @objc func que maneja cómo se mostrará el teclado (esta es su función de usuario)