Цель C: Где удалить наблюдателя для NSNotification? - PullRequest
97 голосов
/ 24 июня 2011

У меня есть объективный класс C. В нем я создал метод init и настроил в нем NSNotification

//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(getData)
                                             name:@"Answer Submitted"
                                           object:nil];

Где мне установить [[NSNotificationCenter defaultCenter] removeObserver:self] в этом классе? Я знаю, что для UIViewController я могу добавить его в метод viewDidUnload Так что же нужно сделать, если я только что создал целевой класс c?

Ответы [ 14 ]

2 голосов
/ 28 июня 2013

Принятый ответ небезопасен и может привести к утечке памяти. Пожалуйста, оставьте незарегистрированную запись в dealloc, но также отмените регистрацию в viewWillDisappear (то есть, конечно, если вы зарегистрируетесь в viewWillAppear) .... ЭТО ТО, ЧТО Я ВСЕГДА ДЕЛАЛ, И ЭТО РАБОТАЕТ ОТЛИЧНО! :)

1 голос
/ 22 января 2017

Важно также отметить, что viewWillDisappear вызывается также, когда контроллер представления представляет новый UIView. Этот делегат просто указывает, что основной вид контроллера представления не виден на дисплее.

В этом случае освобождение уведомления в viewWillDisappear может быть неудобным, если мы используем уведомление, чтобы позволить UIview связываться с родительским контроллером представления.

В качестве решения я обычно удаляю наблюдателя одним из следующих двух способов:

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"viewController will disappear");
    if ([self isBeingDismissed]) {
        NSLog(@"viewController is being dismissed");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
    }
}

-(void)dealloc {
    NSLog(@"viewController is being deallocated");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
}

По тем же причинам, когда я выдаю уведомление в первый раз, мне нужно учитывать тот факт, что в любое время, когда представление с надстройкой появляется над контроллером, тогда запускается метод viewWillAppear. Это, в свою очередь, создаст несколько копий одного и того же уведомления. Поскольку нет способа проверить, активно ли уже уведомление, я устраняю проблему, удаляя уведомление перед его добавлением:

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewController will appear");
    // Add observers
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageGenerated" object:nil]; // This is added to avoid duplicate notifications when the view is presented again
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedImageFromCameraOrPhotolibraryMethodOnListener:) name:@"actionCompleted" object:nil];

}
0 голосов
/ 31 июля 2017
override func viewDidLoad() {   //add observer
  super.viewDidLoad()
  NotificationCenter.default.addObserver(self, selector:#selector(Yourclassname.method), name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}

override func viewWillDisappear(_ animated: Bool) {    //remove observer
    super.viewWillDisappear(true)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}
0 голосов
/ 03 июля 2017

SWIFT 3

Существует два случая использования уведомлений: - они нужны только тогда, когда контроллер вида находится на экране;- они нужны всегда, даже если пользователь открыл другой экран сверх текущего.

Для первого случая правильное место для добавления и удаления наблюдателя:

/// Add observers
///
/// - Parameter animated: the animation flag
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(...)
}

/// Remove observers
///
/// - Parameter animated: the animation flag
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

для второго случая правильноепуть таков:

/// Add observers
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(...)
}

/// Remove observers
///
/// - Parameter animated: the animation flag
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if self.isBeingDismissed // remove only when view controller is removed disappear forever
    || !(self.navigationController?.viewControllers.contains(self) ?? true) {
        NotificationCenter.default.removeObserver(self)
    }
}

И никогда не вставляйте removeObserver в deinit{ ... } - это ОШИБКА!

...