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];
}
Author: Marco, 2014-01-29

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.

Aby dokonać rejestracji, należy wysłać 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.

Aktualizacja dla systemów iOS 9 / macOS 10.11 i nowszych]} W tym celu należy skontaktować się z Działem obsługi klienta. obserwator, jeżeli obserwator jest dealokowany. Nie jest już konieczne ręczne wyrejestrowanie się w metodzie dealloc (lub deinit w języku Swift), jeśli celem wdrożenia jest system iOS 9 lub nowszy lub macOS 10.11 lub nowszy.
 57
Author: rob mayoff,
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];

 6
Author: MAB,
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