Просмотр вызова контроллера не вызывается при использовании метода блока кода NSNotificationCenter с ARC

Когда я использую -addObserverForName: object: queue: usingBlock: за NSNotificationCenter в -viewDidLoad: метод моего контроллера зрения, -dealloc метод заканчивается тем, что не вызывается.

(Когда я удаляю -addObserverForName: object: queue: usingBlock:, -dealloc называется снова.)

С помощью -addObserver: selector: name: object: похоже, нет этой проблемы. Что я делаю неправильно? (Мой проект использует ARC.)

Ниже приведен пример моей реализации, на случай, если я что-то не так делаю здесь:

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  updateResult = YES;
                                              }];

Заранее благодарю за любую помощь.

Я попытался добавить следующее (безрезультатно):

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    if ([self isMovingFromParentViewController]) {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
}

3 ответа

Решение

updateResult является переменной экземпляра, которая предотвращает освобождение объекта, поскольку он сохраняется этим блоком.

Другими словами, у вас есть цикл сохранения. Объект сохраняет блок, а блок сохраняет объект.

Вам потребуется создать слабую или unsafe_unretained ссылку на этот экземпляр и его переменную для потери этой связи.

Добавьте следующее до вашего блока уведомлений:

__unsafe_unretained YouObjectClass *weakSelf = self;

или (если вы используете iOS5 и выше)

__weak YouObjectClass *weakSelf = self;

Затем, внутри этого блока, ссылка на объект через эту новую слабую ссылку:

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  weakSelf.updateResult = YES;
                                              }];

Обратите внимание, что сохраняющие циклы сами по себе неплохие вещи. Иногда вы действительно хотите, чтобы они произошли. Но это те случаи, когда вы уверены, что цикл будет нарушен через определенное время (например, блоки анимации). Цикл прерывается после выполнения блока и удаления из стека.

Это очень вероятно, потому что у вас есть цикл сохранения.

Как правило, это тот случай, когда ваш блок неявно сохраняет себя, а self каким-то образом сохраняет блок. У вас будет цикл сохранения, так как каждый сохраняет другой, и их retainCount, таким образом, никогда не достигнет нуля.

Вы должны активировать предупреждение -Warc-retain-cycles что предупредит вас о таких проблемах.

Так что в вашем случае вы используете переменную updateResult, который я предполагаю, является переменной экземпляра, и это неявно сохранить self, Вместо этого вы должны использовать временную слабую переменную для представления себя и использовать ее в своем блоке, чтобы она не сохранялась и вы прерывали цикл сохранения.

__block __weak typeof(self) weakSelf = self; // weak reference to self, unretained by the block
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                              object:nil
                                               queue:nil
                                          usingBlock:^(NSNotification *note) {
                                              // Use weakSelf explicitly to avoid the implicit usage of self and thus the retain cycle
                                              weakSelf->updateResult = YES;
                                          }];

Это не сохранить цикл.

NSNotificationCenter удерживать блок, блок удерживать self, Так как [NSNotificationCenter defaultCenter]это синглтон, живущий во всем жизненном цикле приложения self косвенные.

Другие вопросы по тегам