objective-c cocoa nsnotificationcenter

objective c - NSNotificationCenter: lista de observadores?



objective-c cocoa (6)

¿Es posible obtener la lista de observadores (objetos y selectores) para un nombre de notificación dado? (NSNotificationCenter)


¿Has probado la propiedad observationInfo de NSObject?

observationInfo Returns a pointer that identifies information about all of the observers that are registered with the receiver.


(iOS 9, Swift 3) Si desea saber qué observadores están actualmente registrados en NotificationCenter , rompa e imprima su descripción de depuración:

(lldb) e print(NotificationCenter.default.debugDescription)

Cada línea de la salida contendrá Nombre (Notificación) , Objeto , Observador , Opciones . Las llamadas múltiples a NotificationCenter.default.addObserver con algún NSNotification.Name darán como resultado múltiples entradas en esta lista.

NÓTESE BIEN. Si bien esto podría ser una información útil cuando se realiza la depuración, no recomendaría administrar observadores en tiempo de ejecución utilizando esta salida.

(fuente: answer basada en useyourloaf )


Creé una categoría en NSNotificationCenter y modifiqué el método addObserver ::::.

Esto es solo para la depuración y nunca debe estar en el código de producción, ya que llevará a la retención de ciclos.

@interface NSNotificationCenter (Tracking) @property (nonatomic) NSMutableArray <NSDictionary *> * observers; @end #import <JRSwizzle/JRSwizzle.h> @implementation NSNotificationCenter (Tracking) + (void)initialize { [super initialize]; [self jr_swizzleMethod:@selector(addObserver:selector:name:object:) withMethod:@selector(SNaddObserver:selector:name:object:) error:nil]; } - (void)SNaddObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject { NSDictionary *obs = @{@"observer" :observer, @"selector" :NSStringFromSelector(aSelector), @"name" :aName }; DDLogDebug(@"observer added : %@", obs); [[self observers] addObject:obs]; [self SNaddObserver:observer selector:aSelector name:aName object:anObject]; } - (NSMutableArray <NSDictionary *> *) observers{ static NSMutableArray <NSDictionary *> * _observers = nil; if (!_observers) { _observers = [NSMutableArray new]; } return _observers; } @end


En lugar de usar NSNotificationCenter, puede probar este ObserversCenter . Y usted puede obtener la lista de observadores.

Acerca de ObserverCenter:

  1. implementa un patrón de múltiples observadores como NSNotificationCenter;
  2. desacopla a los observados y observadores, por lo que no se conocen;
  3. puede suscribirse en una clave especificada;
  4. Puede llamar a la interfaz real al hacer una notificación.

No hay una API pública para consultar a NSNotificationCenter sobre la lista de observadores actuales para cualquier objeto o notificación.

La respuesta anterior describe una solución y proporciona cierto nivel de detalle sobre la propiedad de los observadores, en una subclase de NSNotificationCenter diseñada para recopilar y proporcionar dicha información.

Sin embargo, esta solución solo se puede utilizar con su propio código, que llamará a la subclase de NSNotiicationCenter . ¿Qué pasa con otro código, tanto en el sistema como en las bibliotecas externas que usan el NSNotificationCenter base para registrar / anular el registro de notificaciones?

Sugiero que, en lugar de NSNotificationCenter subclases en NSNotificationCenter , utilice un poco de ObjC de bajo nivel para cambiar las implementaciones del método del NSNotifictionCenter original, reemplazándolas con nuestras propias implementaciones, que funcionarán más o menos como se describe en la respuesta anterior, y llamarán a Implementaciones originales como último acto.

Aquí se explica cómo hacerlo: http://nshipster.com/method-swizzling/

Luego, puede estar seguro de obtener TODOS los observadores de alguna notificación y de que su código es portátil y utilizable con un código de terceros que utiliza directamente NSNotificationCenter .


No creo que haya una manera (oficial) de recuperar la lista de observadores para un nombre de notificación dado desde NSNotificationCenter . Sin embargo, puede crear una subclase de NSNotificationCenter y luego anular los siguientes métodos:

  • + defaultCenter
  • - addObserver:selector:name:object
  • - addObserverForName:object:queue:usingBlock:
  • - removeObserver:
  • - removeObserver:name:object

En las implementaciones de anulación de los métodos de instancia, usted debería hacer un seguimiento de los observadores para un nombre de notificación dado utilizando un diccionario. En cada método de instancia anulado, finalmente llamaría al NSNotificationCenter respectivo de NSNotificationCenter . Además, proporcionaría un método para recuperar su propia lista de observadores para el nombre dado, por ejemplo:

- (id)observerForNotificationName:(NSString *)name

Sin embargo, hay dos problemas con este enfoque: primero, NSMutableDictionary retendría a todos los observadores en una implementación ingenua, que probablemente no sea el mismo comportamiento que implementa NSNotificationCenter . En segundo lugar, tendría que cambiar el código que obtiene el centro de notificaciones predeterminado mediante [NSNotificationCenter defaultCenter] (o cualquier otra instancia de NSNotificationCenter ) para usar su subclase personalizada.

Tenga en cuenta que el primer problema es solucionable utilizando un CFDictionary con devoluciones de llamada de referencia débiles, una clase contenedora con una referencia débil para el observador respectivo o, si se encuentra en un entorno de recolección de basura en Mac OS X, un NSHashTable .