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