ios - pantalla - recuperar notificaciones iphone
iOS Eliminar observador de la notificación: ¿Puedo llamar a esto una vez para todos los observadores? E incluso si no hay ninguno? (2)
Para su primera pregunta, anular el registro incluso cuando no hay observador está bien. Pero por la forma en que está eliminando el observador, [[NSNotificationCenter defaultCenter] removeObserver:someObserver];
eliminará incluso a los observadores de la súper clase que no son altamente recomendados (excepto en dealloc porque el objeto está descargado) pero en viewWillDisappear
debería eliminar a los observadores uno por uno usando [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
Estoy registrando tres observadores en la mayoría de mis controladores de vista. Algunos tienen más, otros menos, pero quiero incluir parte del proceso de registro y anulación del registro en una clase principal. ¿Hay algún problema con llamar a anular el registro incluso si no hay un observador? ¿Y es suficiente un llamado a cancelar el registro para los tres observadores?
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillEnterBackground:)
name:UIApplicationWillResignActiveNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//Has to be unregistered always, otherwise nav controllers down the line will call this method
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Sí, eso eliminará todos los registros en los que el observador es self
. Está documentado en la referencia de clase NSNotificationCenter :
El siguiente ejemplo ilustra cómo anular el registro de
someObserver
para todas las notificaciones para las que se había registrado anteriormente:
[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
Tenga en cuenta que en teoría (pero no, que yo sepa, en la práctica a partir de iOS 7.0), UIViewController
podría tener sus propios registros que no desea eliminar en viewWillDisappear:
Es poco probable que se registre para cualquiera de las notificaciones en la API pública usando addObserver:selector:name:object:
porque eso le impediría registrarse en su subclase UIViewController
, pero ciertamente podría registrarse para notificaciones no públicas ahora o en una versión futura.
Una forma segura de removeObserver:name:object:
registro es enviar removeObserver:name:object:
una vez para cada registro:
- (void)deregisterForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[center removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
Otra forma es usar addObserverForName:object:queue:usingBlock:
para registrarse (en lugar de addObserver:selector:name:object:
. Esto devuelve una nueva referencia de objeto observador para cada registro. Debe guardarlos (tal vez en una variable de instancia NSArray
si no desea crear variables de instancia individuales). Luego pasa cada uno a removeObserver:
para cancelar el registro de su notificación. Ejemplo:
@implementation MyViewController {
NSMutableArray *observers;
}
- (void)registerForKeyboardNotifications {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *queue = [NSOperationQueue mainQueue];
__weak MyViewController *me = self;
observers = [NSMutableArray array];
[observers addObject:[center addObserverForName:UIKeyboardWillShowNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillShow:note];
}]];
[observers addObject:[center addObserverForName:UIKeyboardWillHideNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me keyboardWillHide:note];
}]];
[observers addObject:[center addObserverForName:UIApplicationWillResignActiveNotification
object:nil queue:queue usingBlock:^(NSNotification *note) {
[me applicationWillResignActive:note];
}]];
}
- (void)deregisterForKeyboardNotifications {
for (id observer in observers) {
[[NSNotificationCenter defaultCenter] removeObserver:observer];
}
observers = nil;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self deregisterForKeyboardNotifications];
}
- (void)dealloc {
[self deregisterForKeyboardNotifications];
}
Dado que cada observador devuelto por addObserverForName:object:queue:usingBlock:
es un nuevo objeto que solo tiene un registro, se garantiza que cada llamada a removeObserver:
solo eliminará el registro de ese observador.
Actualización para iOS 9 / macOS 10.11 y posteriores
A partir de iOS 9 y macOS 10.11, NSNotificationCenter
automáticamente el registro de un observador si el observador está desasignado. Ya no es necesario dealloc
registro manualmente en su método dealloc
(o deinit
en Swift) si su destino de implementación es iOS 9 o posterior o macOS 10.11 o posterior.