В Cocoa нужно ли мне удалять объект из режима получения уведомлений KVO при его освобождении?

StackOverflow https://stackoverflow.com/questions/13927

  •  08-06-2019
  •  | 
  •  

Вопрос

Когда я зарегистрирую объект фу чтобы получать уведомления 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top