Re: Observing with GC
Re: Observing with GC
- Subject: Re: Observing with GC
- From: Mark Piccirelli <email@hidden>
- Date: Tue, 26 Feb 2008 17:07:38 -0800
On Feb 26, 2008, at 2:36 PM, Graham wrote:
I hesitate to weigh in on an established thread, but I ran into this
myself a while back.
Isn't part of the purpose of the observer mechanism to allow
observees to proceed with their normal activities blissfully unaware
of any observers that might be looking at 'em?
Yes. As long as an object's class is properly KVO-compliant for a
property you, as the author of that class, shouldn't have to care even
a little bit about what other objects are observing that property.
In which case they won't be keeping track of their observers so have
no easy way to tell them to get lost when they are about to disappear.
Obviously one can design observees to keep a reference to their
observers, but if they need to do that they may as well message them
directly with state changes (though KVO as it stands is obviously
still more convenient).
Right. In general observed objects being destroyed should never try to
shrug off their observers and shouldn't have to. There are a few
reasonable uses for objects observing themselves, and such objects
have to stop observing themselves at some point during their
lifecycle, but I've never seen code like [self
removeObserver:someObjectOtherThanSelf forKeyPath:aKeyPath] that
couldn't be improved upon.
I've probably misunderstood something about the design philosophy
behind KVO, but as everything is up to the observer to decide when
to safely start and stop observing, the possibility of the observee
being dealloced out from underneath the observer is a realistic
possibility that the current design doesn't handle very nicely.
Surely it would be more useful and easier to use if the pattern was
for an observer to observe an object until it decides to stop OR
UNTIL the observee goes away, whichever occurs first. I don't
understand why this second case has to cause an error, as it does now.
Perhaps someone better acquainted with the design can explain why
it's not done this way? Working around this one issue vastly
overcomplicates an observer/observee situation which to my mind
makes KVO less useful than it appears to be.
Situations in which the observee goes away before the observer are
always pretty fishy, and we'll probably never support them. Observers
in general should start observing in response to some event and stop
observing in response to the inverse event. In between something
should be retaining (or strongly referencing, in GC land) the
observee, if only so the observer can stop observing it properly and
not make KVO itself leak memory. In Leopard Sketch for example an
SKTGraphicView starts observing SKTGraphics when its "graphics"
property is bound and stops observing them when the property is
unbound. In between it also starts observing SKTGraphics when they're
added to the bound-to to-many relationship and stops observing them
when they're removed. (SKTGraphicView is doing two levels of
observation here; see the source code.) Pretty straightforward
balancing in both cases. There's no possibility of SKTGraphics being
deallocated out from under the observing SKTGraphicView because they
should be being retained by the array that is the value of the bound-
to to-many relationship, an SKTDocument's "graphics" in the case of
Sketch, anyway.
In this example, an SKTGraphic being deallocated while something's
observing it would be symptomatic of either:
• Something that's not really a memory leak but might as well be. An
SKTGraphicView could probably get away with not removing itself as an
observer of SKTGraphics as they're removed from the bound-to
relationship, but the memory that the KVO machinery allocated when the
SKTGraphicView was added as an observer to the SKTGraphic would never
get deallocated. Even if we (Apple) had just made KVO silently
deallocate that memory when the observee was deallocated it would have
been a waste of memory in the meantime. A potentially large one in
this example, taking into account that many SKTGraphics might be
extant but no longer visible in an SKTGraphicView because of stuff
like undo support.
• Something bad like faulty KVO-compliance for "graphics" in
SKTDocument resulting in the SKTGraphicView not being notified that it
should stop observing individual SKTGraphics.
These sorts of problems are why KVO, in non-GC'ed apps anyway, logs so
crabbily about objects being deallocated while observed. In every case
where the logging happens there was always a moment before that when
the observing should have stopped.
In GC land KVO still has the same requirement that every invocation of
-addObserver:… is balanced by an invocation of -removeObserver:… This
is bad and we know it. The "inverse event" mentioned up above is easy
to make happen when every significant observer has a -dealloc method
anyway. -[SKTGraphicView dealloc] for example does the unbinding
mentioned above. Not so easy when there are no -dealloc methods and
you're trying to avoid writing -finalize methods. We hope to improve
the situation in the future. Another known badness is that the helpful
logging about objects being destroyed with observers still registered
with them is never done when running GC'ed. We hope to improve that too.
-- Mark
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden