iOS Usuń obserwatora z powiadomienia: Czy mogę zadzwonić do tego raz dla wszystkich obserwatorów? A nawet jeśli ich nie ma?
Rejestruję trzech obserwatorów w większości moich kontrolerów. Niektórzy mają więcej, inni mniej, ale chcę włączyć część procesu rejestracji i wyrejestrowania w klasie rodzica. Czy jest jakiś problem z wywołaniem niezarejestrowanego, nawet jeśli nie ma obserwatora? Czy jedno wezwanie do niezarejestrowania wystarczy dla wszystkich trzech obserwatorów?
- (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];
}
2 answers
Tak, to usunie wszystkie rejestracje tam, gdzie obserwator jest self
. Jest to udokumentowane w Nsnotificationcenter klasy odniesienia :
Poniższy przykład ilustruje, jak wyrejestrować
someObserver
dla wszystkich powiadomień, dla których wcześniej zarejestrował się:[[NSNotificationCenter defaultCenter] removeObserver:someObserver];
Zauważ, że w teorii (ale nie, o ile wiem, w praktyce od iOS 7.0), UIViewController
może mieć własne rejestracje, których nie chce usunąć w viewWillDisappear:
. Jest mało prawdopodobne, aby Zarejestruj się dla któregokolwiek z powiadomień w publicznym API za pomocą addObserver:selector:name:object:
, ponieważ wykluczyłoby to rejestrację dla nich w podklasie UIViewController
, ale z pewnością mogłoby to zarejestrować się dla niepublicznych powiadomień teraz lub w przyszłej wersji.
removeObserver:name:object:
jeden raz:
- (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];
}
Innym sposobem jest użycie addObserverForName:object:queue:usingBlock:
do rejestracji(zamiast addObserver:selector:name:object:
). To zwraca nowe odniesienie do obiektu obserwatora dla każdej rejestracji. Musisz je uratować. (być może w zmiennej instancji NSArray
, jeśli nie chcesz tworzyć pojedynczych zmiennych instancji). Następnie przekazujesz je removeObserver:
, aby wyrejestrować ich powiadomienie. Przykład:
@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];
}
Ponieważ każdy obserwator zwrócony przez addObserverForName:object:queue:usingBlock:
jest nowym obiektem, który ma tylko jedną rejestrację, każde wywołanie removeObserver:
ma gwarancję usunięcia tylko jednej rejestracji obserwatora.
dealloc
(lub deinit
w języku Swift), jeśli celem wdrożenia jest system iOS 9 lub nowszy lub macOS 10.11 lub nowszy.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-10 19:38:53
Na pierwsze pytanie, nawet gdy nie ma obserwatora jest OK.
Ale jeśli chodzi o sposób, w jaki usuwasz obserwatora, [[NSNotificationCenter defaultCenter] removeObserver:someObserver];
usunie nawet super class observers, który jest wysoce niezalecany (z wyjątkiem dealloc, ponieważ obiekt jest rozładowany), ale w viewWillDisappear
powinieneś usunąć obserwatorów jeden po drugim używając [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-28 23:28:01