Когда я должен удалить наблюдателей? Ошибка об освобождении объектов перед удалением наблюдателей - PullRequest
32 голосов
/ 13 июня 2009

Я пытаюсь использовать наблюдение значения ключа в одном из моих классов. Я регистрирую наблюдателей в методе init и удаляю / отменяю их регистрацию в dealloc, но я получаю следующую ошибку, которая, по-видимому, возникает до вызова моего метода dealloc, согласно моим отладочным выводам.

Экземпляр 0x583870 класса TekkPoint освобождается, пока наблюдатели значения ключа все еще зарегистрированы в нем. Информация о наблюдениях просачивается и может даже ошибочно присоединиться к какому-либо другому объекту. Установите точку останова на NSKVODeallocateBreak, чтобы остановиться здесь в отладчике. Вот текущая информация наблюдения: ( Контекст: 0x0, Свойство: 0x536400> Контекст: 0x0, Свойство: 0x55aba0> )

Есть ли какой-то особый способ, которым я должен удалить наблюдателей? Или, может быть, в каком-то конкретном месте, где я должен их удалить?

Согласно этому вопросу Я все делаю правильно, но почему я получаю это сообщение об ошибке?

Вот моя рутина деллок:

- (void)dealloc {
  // Remove all observers.
  for (NSString *path in [TekkPoint observedPaths]) {
    [self removeObserver:[option_ tChart]
          forKeyPath:path];

  }

  [description_ release];
  [weight_ release];
  [super dealloc];
}

Одна вещь, которая может показаться странной в моей реализации, это то, что я добавляю и удаляю наблюдателей из наблюдателя, может ли это вызвать мою проблему?

Ответы [ 4 ]

46 голосов
/ 13 июня 2009

Ах. Вы наблюдаете объект TekkPoint от объекта SomethingElse, а объект SomethingElse - это тот, кто добавляет и удаляет наблюдателей, верно? (Это нормальный способ, которым все делается; я просто пытаюсь уточнить.)

Похоже, ваш TekkPoint объект был освобожден, в то время как SomethingElse, который наблюдает, все еще находится вокруг. Метод SomethingElse dealloc не вызывается, потому что освобождается TekkPoint, а не SomethingElse.

Если вы планируете наблюдать за объектом, который может исчезнуть до исчезновения наблюдателя, вам нужно каким-то образом уведомить наблюдателей, что они должны удалить своих наблюдателей. Ваш TekkPoint может иметь свойство alive, которое также будет наблюдаться SomethingElse, и когда оно будет установлено на NO, тогда каждый, наблюдающий TekkPoint, удалит себя как наблюдателя.

2 голосов
/ 13 июня 2009

Вы звоните [super dealloc] до того, как вы удалите своих наблюдателей? Вызов супер dealloc слишком рано может привести к такой ошибке.

0 голосов
/ 14 мая 2014

почему бы вам позвонить

[super dealloc]

Из яблочной документации на dealloc

In an implementation of dealloc, do not invoke the superclass’s implementation
0 голосов
/ 13 июня 2009

Нормальный код выглядит примерно так:

- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

Дважды проверьте вашу подпись вашего метода dealloc (Цель C очень неумолима и никогда не предупредит вас, когда вы напутаете название метода). Например, если имя вашего метода было «dealoc» (с одним l), ваш dealloc никогда бы не был вызван.

В противном случае отредактируйте свой вопрос, включив в него процедуру dealloc.

...