Как удалить KVO из слабой собственности?

У меня есть представление (мы будем называть это представление A), которое имеет weak свойство для своего супервизора (вид B). Просмотреть представление KVO о его просмотре, просмотреть B. Поскольку ссылка A на представление B является слабым свойством (чтобы предотвратить цикл сохранения), как я могу удалить наблюдателя (A наблюдение B)? View Ссылка A на представление B получает nil'd, прежде чем у меня есть шанс удалить его.

Выводы B, поскольку контроллер представления имеет сильную ссылку на A. Вот сообщение об утечке журнала:

 An instance 0x9ac5200 of class UITableView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info: <NSKeyValueObservationInfo 0x8660360> ( <NSKeyValueObservance 0x8660320: Observer: 0x8660020, Key path: contentOffset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x8660020, Property: 0x864ac80> ) 

B – UITableView. Установка точки останова на NSKVODeallocateBreak дает бесполезные результаты.

В A removeFromSuperview я пытаюсь удалить наблюдателя, но ссылка A на B уже равна nil .

Переключение на unsafe_unretained и делать что-то более вручную или вызывать [A removeFromSuperview] в dealloc диспетчера просмотра решает проблему. Я хотел бы знать, как решить эту проблему, используя weak свойство.

Вот соответствующий код: https://gist.github.com/2822776

Я считаю, что какой-либо код, требуемый специально для этого случая, действительно лишний, поскольку удаление может быть автоматизировано.

С введением ARC Apple должна была обеспечить автоматическое удаление наблюдателей, которые фиксировали бы подобные случаи, но, к сожалению, они этого не сделали. Но я создал свою собственную категорию, которая добавляет эту недостающую функцию: https://github.com/krzysztofzablocki/SFObservers. Я объяснил, как я это сделал в своем блоге: http://www.merowing.info/2012/ 03 / автоматического удаления-оф-NSNotificationCenter-или-КВО-наблюдатели /

Если вы посмотрите на мое решение, вы заметите, что он гарантирует, что вызывается исходный код, даже если один из методов вызывает другие, так что даже если яблоко изменит свое внутреннее поведение, категория будет по-прежнему работать нормально 🙂

Вы можете определить явное слабое свойство, ссылающееся на супервизор, а затем наблюдать за self с помощью ключевого пути, например @"propertyReferringSuperview.propertyOfSuperview" ? Когда вы получаете уведомление self.propertyReferringSuperview == nil , вы проверяете, будет ли self.propertyReferringSuperview == nil и прекратить наблюдение @"propertyReferringSuperview.propertyOfSuperview" .

Вместо добавления слабого свойства вы можете просто использовать свойство willMoveToSuperview: и реализовать willMoveToSuperview: для добавления / удаления наблюдения willMoveToSuperview: .

 - (void)willMoveToSuperview:(UIView *)newSuperview { [self.superview removeObserver:self forKeyPath:@"contentOffset" context:context]; [newSuperview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:context]; [super willMoveToSuperview:newSuperview]; // optional as default implementation does nothing } 
  • Декодирование AirPlay Mirroring Protocol
  • Разделение строки CamelCase в словах, разделенных пробелами, в Swift
  • Может ли быстрое закрытие установить значение по умолчанию при использовании в качестве параметра в функции?
  • В чем разница между mach_vm_allocate и vm_allocate?
  • Объект Mac, созданный с помощью iphonesimulator gcc 4.2
  • Не удается загрузить приложение в App Store?
  • Большая копия файла с GCD - Dispatch IO потребляет большие объемы памяти
  • Это ошибка в NSIndexSet enumerateIndexesUsingBlock?
  • Общение между iPhone и Mac
  • Невозможно выполнить cmake cpp-netlib с фреймворком Boost, созданным с помощью скрипта boost.sh
  • Ошибка Xcode 4.6.1 после установки OSX Yosemite
  • Давайте будем гением компьютера.