В Какао мне нужно удалить объект из получения уведомлений KVO при его освобождении? - PullRequest
23 голосов
/ 18 августа 2008

Когда я зарегистрировал объект foo для получения уведомлений KVO от другого объекта bar (используя addObserver: ...), если я затем освобождаю foo мне нужно отправить removeObserver:forKeyPath: сообщение на бар в -dealloc?

Ответы [ 3 ]

38 голосов
/ 18 августа 2008

Вам нужно использовать -removeObserver:forKeyPath:, чтобы удалить наблюдателя до запуска -[NSObject dealloc], так что да, выполнение этого в методе -dealloc вашего класса сработает.

Лучше, чем это, хотя было бы иметь детерминированную точку, в которой независимо от того, кто владеет объектом, который выполняет наблюдение, может сказать ему, что оно сделано и (в конце концов) будет освобождено. Таким образом, вы можете немедленно прекратить наблюдение, когда объект, выполняющий наблюдение, больше не нужен, независимо от того, когда он фактически отменен.

Это важно иметь в виду, потому что время жизни объектов в Какао не так детерминировано, как некоторые думают. Сами различные фреймворки Mac OS X будут отправлять ваши объекты -retain и -autorelease, продлевая срок их службы за пределы того, что вы могли бы иначе представить.

Более того, когда вы перейдете к сборке мусора в Objective-C, вы обнаружите, что -finalize будет работать в очень разное время - и в совершенно разных контекстах - чем -dealloc. С одной стороны, финализация происходит в другом потоке, поэтому вы действительно не можете безопасно отправить -removeObserver:forKeyPath: другому объекту методом -finalize.

Придерживайтесь управления памятью (и другими дефицитными ресурсами) в -dealloc и -finalize и используйте отдельный метод -invalidate, чтобы владелец сообщил объекту, что вы покончили с ним в детерминированной точке; делать такие вещи, как удаление наблюдений КВО там. Намерение вашего кода будет более ясным, и у вас будет меньше мелких ошибок, о которых нужно позаботиться.

5 голосов
/ 29 августа 2008

Немного дополнительной информации, которую я получил благодаря болезненному опыту: хотя NSNotificationCenter использует обнуление слабых ссылок при работе под сборкой мусора, KVO этого не делает. Таким образом, вы можете избежать удаления наблюдателя NSNotificationCenter при использовании GC (при использовании retain / release вам все равно нужно удалить наблюдателя), но вы все равно должны удалить наблюдателей KVO, как описывает Крис.

2 голосов
/ 15 сентября 2008

Определенно согласен с Крисом в комментарии «Придерживайся памяти (и других дефицитных ресурсов) в -dealloc и -finalize ...». Много раз я вижу, как люди пытаются сделать недействительными объекты NSTimer в своих функциях dealloc. Проблема в том, что NSTimer сохраняет свои цели. Таким образом, если целью этого NSTimer является self, dealloc никогда не будет вызван, что приведет к некоторым потенциально неприятным утечкам памяти.

Сделайте недействительными в -invalidate и выполните другую очистку памяти в ваших dealloc и finalize.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...