¿Por qué mi NSNotificación es su observador llamado varias veces?


Dentro de una Aplicación hago uso de varios viewcontroller. En un viewcontroller un observador se inicializa de la siguiente manera:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];

Incluso cuando se elimina el NSNotification antes de inicializar el número de ejecuciones de myMethod: se suma por la cantidad de vistas repetidas en el respectivo viewcontroller.

¿por Qué sucede esto y cómo puedo evitar myMethod: ser llamado más de una vez.

Nota: Me aseguré mediante el uso de puntos de interrupción que no cometí errores al llamar producida después de la notificación varias veces.

Editar: Así es como se ve mi postNotificación

NSArray * objects = [NSArray arrayWithObjects:[NSNumber numberWithInt:number],someText, nil];
NSArray * keys = [NSArray arrayWithObjects:@"Number",@"Text", nil];
NSDictionary * userInfo = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];

Editar: incluso después de mover mi suscripción a viewwillappear: Obtengo el mismo resultado. myMethod: se llama varias veces. (número de veces que recarga el viewcontroller).

-(void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myMethod:) name:@"MyNotification" object:nil];
}

Editar: algo parece estar mal con mi ciclo de vida. viewDidUnload y dealloc no son llamados, sin embargo viewdiddisappear es llamado.

La forma en que envio mi Viewcontroller a la pila es como sigue donde parent es una subclase tableview (al hacer clic en la fila se inicia este viewcontroller:

detailScreen * screen = [[detailScreen alloc] initWithContentID:ID andFullContentArray:fullContentIndex andParent:parent];
[self.navigationController pushViewController:screen animated:YES];

Solución:

Mover la eliminación de nsnotification a viewdiddisappear hizo el truco. Gracias por la orientación!

Author: BarryK88, 2013-11-06

4 answers

Basado en esta descripción, una causa probable es que sus viewcontroller están retenidos en exceso y no liberados cuando cree que lo están. Esto es bastante común incluso con ARC si las cosas se retienen demasiado. Por lo tanto, usted piensa que solo tiene una instancia de un viewcontroller dado activo, mientras que en realidad tiene varias instancias en vivo, y todos escuchan las notificaciones.

Si estuviera en esta situación, pondría un punto de interrupción en el método dealloc de viewcontroller y me aseguraría de que es desasignado correctamente, si ese es el diseño previsto de su aplicación.

 35
Author: Jaanus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 00:58:13

¿En qué métodos inscribió a los observadores?

Apple recomienda que los observadores estén registrados en viewWillAppear: y no registrados en viewWillDissapear:

¿Estás seguro de que no registras al observador dos veces?

 35
Author: Igor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-12 08:13:06

Se encontró con este problema en una aplicación que ejecuta swift. La aplicación recibió la notificación una vez cuando se lanzó por primera vez. la notificación aumenta el número de veces que entras en segundo plano y regresas. i. e

  • app launches one-add observer gets gets called once in view will appear or view did load-notification is called once
  • aplicación entra en segundo plano y vuelve, agregar observador se llama de nuevo en la vista aparecerá o vista hizo cargar. se llama a la notificación doblemente.
  • el número aumenta el número de veces que entras en segundo plano y regresas.
  • el código en la vista desaparecerá no hará ninguna diferencia ya que la vista todavía está en la pila de ventanas y no se ha eliminado de ella.

Solución: observe aplicación renunciará activa en su controlador de vista:

  NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationWillResign:", name: UIApplicationWillResignActiveNotification, object: nil)

  func applicationWillResign(notification : NSNotification) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
  }

Esto asegurará que su controlador de vista elimine el observador de la notificación cuando la vista pase a segundo plano.

 3
Author: abhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-03 01:26:51

Es muy posible que se esté suscribiendo a las notificaciones

[[NSNotificationCenter defaultCenter] postNotificationName:@"myNotification" object:self userInfo:userInfo];

Antes de que self se inicialice. Y tratando de darse de baja 'auto' que realmente no está suscrito a, y obtendrá todo global myNotification notificaciones.

Si su vista se conectó en IB, use - awakeFromNib: como punto de partida para registrarse para recibir notificaciones

 1
Author: lead_the_zeppelin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 00:43:56