objective-c ios dealloc nsnotificationcenter addobserver

objective c - Agregar y eliminar observadores a NSNotificationCenter en un UIViewController



objective-c ios (5)

¿Por qué no lo harías en viewWillAppear / viewDidDisappear ? Solo te importan las notificaciones cuando tu vista se muestra de todos modos, ¿verdad?

Observando varios ejemplos de Apple (por ejemplo, Agregar música ) en los que veo que agregan observadores al NSNotificationCenter predeterminado en viewDidLoad , luego los eliminan en dealloc . Esto parece peligroso ya que viewDidLoad se puede llamar varias veces sin que se dealloc . Esto luego agregaría el mismo observador varias veces, haciendo que se llame al controlador varias veces.

Una solución a esto sería eliminar también a los observadores en viewDidUnload , pero esto significaría que el mismo observador podría eliminarse por segunda vez en dealloc que parece ser un problema potencial.

¿Qué me estoy perdiendo?


Hay muchas discusiones sobre cómo eliminar las notificaciones de la manera correcta. Por ejemplo:

Le sugiero que elimine los observadores en los métodos de ciclo de vida viewWillDisappear (o viewDidDisappear ) y viewDidUnload . ( Nota: viewDidUnload está en desuso y no debería implementarse en iOS6 +; consulte iOS 6 - viewDidUnload migrar a didReceiveMemoryWarning? )

Una nota importante:

viewDidUnload se garantiza que se llame a viewDidUnload no es un método de ciclo de vida estándar.

De Apple doc:

viewDidUnload Cuando ocurre una condición de poca memoria y no se necesitan las vistas del controlador de vista actual, el sistema puede optar por eliminar esas vistas de la memoria. Se llama a este método después de que se haya lanzado la vista del controlador de vista y es su oportunidad de realizar cualquier limpieza final.

En su lugar, se llama a dealloc siempre que el número de referencias para ese receptor sea cero.

Espero eso ayude.

Editar

Para completar, puedes ver este enlace sobre cómo avoid-nsnotification-removeobserver . El enlace proporciona algunas pautas útiles para eliminar el observador (vea también los comentarios). El autor lo hace en los métodos viewDidAppear / viewDidDisappear , ya que viewWillAppear y viewWillDisappear no siempre se llaman correctamente en muchas aplicaciones. Es tu elección.

Si desea asegurarse de eliminar a los observadores de la manera correcta, dealloc registro en el método dealloc o cuando la vista esté completamente descargada como escribió en el segundo comentario. Pero asegúrese de que dealloc será llamado en el futuro. En otras palabras, como ya mencioné, si el controlador continúa vivo, ya que algún otro objeto tiene una referencia a él, el método nunca será llamado. En este caso el controlador sigue recibiendo notificaciones.


Para las personas que se han topado en esta página más recientemente, la eliminación de observadores podría no ser más necesaria. La sección "Discusión" de addObserver(_:selector:name:object:) docs dice:

Si su aplicación se dirige a iOS 9.0 y versiones posteriores o macOS 10.11 y versiones posteriores, no necesita anular el registro de un observador en su método dealloc . De lo contrario, debe llamar a removeObserver(_:name:object:) antes de que el observador o cualquier objeto pasado a este método se desasigne.


Puede agregarObserver en viewWillAppear y eliminarObserver en viewWillDisappear. pero viewWillAppear puede ser llamado muchas veces. para que pueda eliminar la Notificación primero y luego addObserver.

-(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:YES]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillShowNotification" object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillHideNotification" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)name:@"UIKeyboardWillShowNotification"object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)name:@"UIKeyboardWillHideNotification"object:nil]; } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:YES]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillShowNotification" object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIKeyboardWillHideNotification" object:nil]; }


- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self .........] } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self .........]; }