Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you remove KVO from a weak property?

I have a view (we'll call this view A) that has a weak property to its superview (view B). View A KVO's its superview, view B. Since view A's reference to view B is a weak property (to prevent a retain cycle), how can I remove the observer (A observing B)? View A's reference to view B gets nil'd out before I have a chance to remove it.

A outlives B since the view controller has a strong reference to A. Here's the leaking log message:

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 is a UITableView. Setting a breakpoint at NSKVODeallocateBreak yields useless results.

In A's removeFromSuperview, I try to remove the observer but A's reference to B is already nil.

Switching to unsafe_unretained and do things more manually or calling [A removeFromSuperview] in the view controller's dealloc solves the problem. I'd like to know how to solve this using a weak property though.

Here's the relevant code: https://gist.github.com/2822776

like image 403
Sam Soffes Avatar asked May 29 '12 04:05

Sam Soffes


2 Answers

I find any kind of code required specially for this case really unnecessary as removal can be automated.

With the introduction of ARC, Apple should have provide automatic removal of observers that would fix cases like this, but unfortunately they didn't. But I've made my own category that adds this lacking feature: https://github.com/krzysztofzablocki/SFObservers I've explained how I did manage that on my blog: http://www.merowing.info/2012/03/automatic-removal-of-nsnotificationcenter-or-kvo-observers/

If you look at my solution you will notice, that it makes sure that original code is called, even if one of the methods call other ones, so that even if apple changes its internal behavior the category will still work fine :)

like image 131
Krzysztof Zabłocki Avatar answered Nov 12 '22 04:11

Krzysztof Zabłocki


You could define an explicit weak property referencing the superview and then observe self with a key path like @"propertyReferringSuperview.propertyOfSuperview"? When you get a KVO notification, you check if self.propertyReferringSuperview == nil and stop observing @"propertyReferringSuperview.propertyOfSuperview".

like image 1
Vadim Avatar answered Nov 12 '22 05:11

Vadim