Re: Get error message about registered observers when Object receives dealloc message
Re: Get error message about registered observers when Object receives dealloc message
- Subject: Re: Get error message about registered observers when Object receives dealloc message
- From: Quincey Morris <email@hidden>
- Date: Sun, 6 Sep 2009 11:32:46 -0700
On Sep 6, 2009, at 05:46, Roland King wrote:
The note however says that in order to reduce the amount of
finalizer methods written just to do KVO registration removal, the
runtime now does it for you automatically in 10.6. So if you're
observing something and are collected, the observations you
registered are automatically removed. It doesn't say if it works the
other way around, ie if A is observing B and B is collected, whether
A's observation is removed; if it were not, when A is eventually
collected I'm not sure what would happen as A's still outstanding
observation on a non-existant object would be removed. Of course
that shouldn't happen as A should have a reference to B anyway in
that case in order to do KVO teardown the normal way so B should
always persist at least as long as A does. Or even the built-in
runtime ability to teardown your KVO for you must keep a reference
to B in order to do that job so .. it's probably never an issue.
[...]
["]With the addition of support for Objective-C garbage collection
to Foundation in Mac OS 10.5 one of the basic rules of key-value
observing (KVO) remained, and still applied to garbage-collected
applications: all invocations of KVO's -
addObserver:forKeyPath:options:context: method must be balanced by
invocations of -removeObserver:forKeyPath: or KVO will leak memory.
(KVO logs when it senses failure to follow this rule but only when
running non-garbage-collected.) The same rule applied to use of
KVO's NSArray batched observer registration methods. This resulted
in situations in which classes of observers had to have -finalize
methods just to do observer deregistration when they otherwise would
not have to. -finalize methods are supposed to be rarer than that.
In Mac OS 10.6, explicit removal of observers when they're finalized
is now never necessary. KVO automatically removes observers as
they're collected. Actually, in Mac OS 10.6 all invocations of -
[NSObject(NSKeyValueObserverRegistration)
removeObserver:forKeyPath:] and -[NSArray
(NSKeyValueObserverRegistration)
removeObserver:fromObjectsAtIndexes:forKeyPath:] do virtually
nothing when either the receiver or the observer is being finalized
(so it's not very bad for performance to leave them there in
applications that still have to run on Mac OS 10.5).["]
I'm trying to be careful here not to say anything stupid or just plain
wrong, but ...
There are two separate issues in the GC case. One deals with the need
to provide a mechanism for observers to remove their observations
before they're destroyed. (Notice that the above quote says
"observers", not "observed objects" or just "objects".) If it's
illegal for an observer to reach its moment of destruction with a
observation still in place, then (this release note seems to say) you
were previously forced (oftener than is desirable) to provide a
'finalize' method as a safety clean-up choke point. So now that clean-
up behavior comes for free.
This says nothing about the need to to remove observations of an
*observed* object that's being collected. I suspect that in 10.6, if
both the observed and observer objects are being collected in the same
cycle, then removing the observers happens automatically first (vid.
the last quoted sentence). I suspect that in 10.5 and 10.6, if the
observed object is collected, but the observers are not being
collected, you will get the error message about an object being
finalized with observations still in place.
Note 1: It seemed to me that KVO observers *were* being removed in
Leopard under GC. At least I thought I had seen situations where there
was no explicit invocation of 'removeObserver:' that didn't complain
when the relevant observer objects were collected. Maybe that happened
sometimes but not always. Maybe I was just fooling myself.
Note 2: Compare this with NSNotificationCenter-style observations
under GC. Those have always been removed automatically. (And what a
heady sense of freedom it is, not having to write 'removeObserver:'
invocations. :) )
The second issue is the larger one that it's unsafe in 'finalize' to
message other objects that might themselves be in the process of
collection. That is, specifically, if you wrote a 'finalize' in an
observer object class in order to remove its observations, you might
not be able to send the 'removeObserver:' message to the observed
object if it was being collected too. Catch-22.
It's this *second* issue which motivated my comment about needing to
initiate clean-up before rather than during 'finalize'. The first
issue is really about the circumstances when you can avoid writing any
clean-up code at all.
_______________________________________________
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