Когда я зарегистрировал объект foo для получения уведомлений KVO с другого объекта bar (используя addObserver:...), если я затем освобожу foo Мне нужно отправить сообщение removeObserver:forKeyPath:
в bar в -dealloc?
В Cocoa мне нужно удалить объект из получения уведомлений KVO при его освобождении?
Ответ 1
Вам нужно использовать -removeObserver:forKeyPath:
для удаления наблюдателя до запуска -[NSObject dealloc]
, так что да, выполнение этого в методе -dealloc
вашего класса будет работать.
Лучше, чем это было бы иметь детерминированный момент, когда все, что принадлежит объекту, который выполняет наблюдение, может сказать, что оно сделано, и будет (в конечном счете) освобождено. Таким образом, вы можете прекратить наблюдение сразу же, когда вещь, выполняющая наблюдение, больше не нужна, независимо от того, когда она фактически освобождена.
Это важно иметь в виду, потому что время жизни объектов в Cocoa не так детерминировано, как кажется некоторым людям. Различные каркасы Mac OS X будут отправлять ваши объекты -retain
и -autorelease
, продлевая срок их службы за пределы того, что вы могли бы подумать, что это будет.
Кроме того, когда вы делаете переход на сборку мусора Objective-C, вы обнаружите, что -finalize
будет работать в самые разные моменты времени - и в самых разных контекстах, чем -dealloc
. Во-первых, финализация происходит в другом потоке, поэтому вы действительно не можете безопасно отправлять -removeObserver:forKeyPath:
другому объекту в методе -finalize
.
Придерживайтесь управления памятью (и другого ограниченного ресурса) в -dealloc
и -finalize
и используйте отдельный метод -invalidate
, чтобы владелец сообщил об этом объект, который вы сделали с ним в детерминированной точке; делайте такие вещи, как удаление наблюдений KVO. Цель вашего кода будет более понятной, и у вас будет меньше тонких ошибок, чтобы позаботиться.
Ответ 2
Немного дополнительной информации, которую я получил от мучительного опыта: хотя NSNotificationCenter использует обнуление слабых ссылок при работе под сборкой мусора, KVO этого не делает. Таким образом, вы можете уйти, не удаляя наблюдателя NSNotificationCenter при использовании GC (при использовании сохранения/освобождения вам все равно нужно удалить своего наблюдателя), но вы все равно должны удалить своих наблюдателей KVO, как описывает Крис.
Ответ 3
Определенно согласен с Крисом в управлении "Придерживайтесь памяти (и другого ограниченного ресурса) в -dealloc и -finalize...". Много раз я увижу, что люди пытаются аннулировать объекты NSTimer в своих функциях dealloc. Проблема в том, что NSTimer сохраняет цели. Итак, если целью этого NSTimer является self, dealloc никогда не будет вызван, что приведет к некоторым потенциально неприятным утечкам памяти.
Недействительно в -invalidate
и выполните очистку памяти в dealloc
и finalize.