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