notification - observer ios swift
NSNotificationCenter addObserver en Swift (11)
¿Cómo agregar un observador en Swift al centro de notificaciones predeterminado? Estoy tratando de 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];
Swift 3.0 en Xcode 8
Swift 3.0 ha reemplazado muchas API "de tipo estricto" con "tipos de envoltura" struct
, como es el caso de NotificationCenter. Las notificaciones ahora se identifican por una struct Notfication.Name
lugar de por String
. Consulte la guía Migración a 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 notificación del sistema ahora están definidos como constantes estáticas en Notification.Name
; es decir .UIDeviceBatteryLevelDidChange
, .UIApplicationDidFinishLaunching
, .UITextFieldTextDidChange
, etc.
Puede extender Notification.Name
con sus propias notificaciones personalizadas para mantener la coherencia con las notificaciones del sistema:
// Definition:
extension Notification.Name {
static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}
// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)
Swift 4.0 y Xcode 9.0+:
Enviar (Publicar) Notificació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 función-método para la notificación recibida:
@objc func methodOfReceivedNotification(notification: Notification) {}
Swift 3.0 y Xcode 8.0+:
Enviar (Publicar) Notificació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)
Controlador de método 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:
Enviar (Publicar) Notificación
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
Recibir (Obtener) Notificación
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)
Controlador de método para la notificación recibida
func methodOfReceivedNotification(notification: NSNotification){
// Take Action on Notification
}
Para versiones históricas de Xcode ...
Enviar (Publicar) Notificació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
Controlador de método para la notificación recibida
func methodOfReceivedNotification(notification: NSNotification) {
// Take Action on Notification
}
Anote ya sea 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
}
Declara un nombre de notificación
extension Notification.Name { static let purchaseDidFinish = Notification.Name("purchaseDidFinish") }
Puedes 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"] }
Publique su notificación
NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
desde iOS 9 y OS X 10.11. Ya no es necesario que un observador de NSNotificationCenter se desregistre a sí mismo cuando se lo desasigna. más información
Para una implementación basada en block
, necesitas hacer un baile débil y fuerte si quieres utilizar el self
dentro del bloque. más información
Debemos eliminar la notificación también.
Ex.
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
En swift 2.2 - XCode 7.3, usamos #selector
para NSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
Es igual que la API de Objective-C, pero usa la sintaxis 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
}
Ver referencia de clase NSNotificationCenter , Interactuar con las API de Objective-C
Soy capaz de hacer una de las siguientes acciones 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 estaría usando Swift 2.0):
$xcrun swift --version
Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
Una buena manera de hacer esto es usar el addObserver(forName:object:queue:using:)
lugar del método addObserver(_:selector:name:object:)
que se usa a menudo 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 puedes usar un cierre en lugar de un método si quieres:
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 que uses cadenas de selección que el compilador no pudo verificar de forma estática y que, por lo tanto, eran frágiles para romperlas si se cambia el nombre del método, pero Swift 2.2 y Más tarde incluya #selector
expresiones #selector
que solucionan ese problema.
En Swift 3, Xcode 8.2: - Comprobar el 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 sintaxis 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. Otro tipo se puede seleccionar de la opción disponible
el Selector es de tipo @objc func que controla cómo se mostrará el teclado (esta es su función de usuario)
Pasar datos utilizando NSNotificationCenter
También puede pasar datos usando NotificationCentre en swift 3.0 y NSNotificationCenter en swift 2.0.
Versión Swift 2.0
Pase información usando 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 Swift 3.0
El userInfo ahora toma [AnyHashable: Any]? como un 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 origen utilizando NotificationCentre (swift 3.0) y NSNotificationCenter (swift 2.0)