2011-04-14 14 views
36

En este momento, la API no parece proporcionar una forma de detectar si un observador ya ha sido agregado para una NSNotificación en particular. ¿Cuál es la mejor manera de evitar agregar múltiples observadores NSNotification que no sea mantener una bandera en su extremo para realizar un seguimiento? ¿Alguien ha creado una categoría para facilitar esto?¿Cómo evitar agregar múltiples NSNotification observador?

+0

¿Puede dar un ejemplo de una situación donde esto podría suceder, o por qué esto debería ser un problema? –

Respuesta

64

Una forma de evitar que se agreguen observadores duplicados es llamar explícitamente a removeObserver para el destino/selector antes de volver a agregarlo. Me imagino que usted puede agregar esto como un método categoría:

@interface NSNotificationCenter (UniqueNotif) 

- (void)addUniqueObserver:(id)observer selector:(SEL)selector name:(NSString *)name object:(id)object { 

     [[NSNotificationCenter defaultCenter] removeObserver:observer name:name object:object]; 
     [[NSNotificationCenter defaultCenter] addObserver:observer selector:selector name:name object:object]; 

} 

@end 

Esto supone que el sólo se añadirá un observador único para cada objetivo para cualquier nombre de notificación, ya que se eliminarán todos los observadores existentes para ese nombre de la notificación.

+1

Aquí está usando "observador" y "objetivo" de una manera muy divertida y no estándar. El "observador" en 'addObserver ...' indica el objeto que recibirá un mensaje cuando se publique la notificación, _no_ el método que conformará ese mensaje. No hay noción de "objetivo" en las notificaciones. Lo que está llamando un "objetivo" se menciona en los documentos como "observador". –

+2

La variable de destino indica dónde debe buscar el tiempo de ejecución del objeto. Cambié el objetivo del nombre arg al observador para eliminar cualquier posible confusión. – futureelite7

+0

Si bien mi "no puede responder" puede haber sido demasiado literal (un objeto no puede detectar a los observadores), esta respuesta es, en el mejor de los casos, una mala práctica. Un mejor consejo para el PO sería utilizar una implementación diferente a la publicación y observación de notificaciones para este caso de uso. Si una notificación solo pretende tener un único observador, el uso de un delegado y un protocolo no solo hace cumplir esto, sino que también deja en claro la relación entre el objeto y su delegado. – XJones

18

Swift 3, 4:

import Foundation 

extension NotificationCenter { 
    func setObserver(_ observer: AnyObject, selector: Selector, name: NSNotification.Name, object: AnyObject?) { 
     NotificationCenter.default.removeObserver(observer, name: name, object: object) 
     NotificationCenter.default.addObserver(observer, selector: selector, name: name, object: object) 
    } 
} 

Swift 2:

import Foundation 

extension NSNotificationCenter { 
    func setObserver(observer: AnyObject, selector: Selector, name: String?, object: AnyObject?) { 
     NSNotificationCenter.defaultCenter().removeObserver(observer, name: name, object: object) 
     NSNotificationCenter.defaultCenter().addObserver(observer, selector: selector, name: name, object: object) 
    } 
} 
+0

me dio ejemplo de agregar observador usando esta extensión en swift 3.0 –

1

La respuesta upvoted con extension NotificationCenter { ... } no funcionó para mí, ya que mi aplicación fue la creación de una nueva instancia de viewController (esto tenía un observador de notificaciones) cada vez que se publicaba una notificación, por lo que se eliminó un n observador en una nueva instancia de una vista. Obviamente, el controlador no funciona. Instancias anteriores de viewController que tenían Notification Observers se estaban llamando.

Lo siguiente funcionó para mí, ya que esto quitaba el Notification Observer tan pronto como la vista se estaba desapareciendo.

// Notification observer added 

override func viewWillAppear(_ animated: Bool) { 

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


} 


// Notification observer removed 

override func viewWillDisappear(_ animated: Bool) { 

    NotificationCenter.default.removeObserver(self, name: Notification.Name("myNotification"), object: nil) 


} 
+1

mejor addObserver en 'viewDidAppear' en lugar de' viewWillAppear'. – dimpiax