Re: Cannot remove an observer ... because it is not registered as an observer.
Re: Cannot remove an observer ... because it is not registered as an observer.
- Subject: Re: Cannot remove an observer ... because it is not registered as an observer.
- From: Steve Steinitz <email@hidden>
- Date: Tue, 6 May 2008 23:27:29 +1000
Summary:
KVO compliance discussion
Detailed problem description
Request (to Jens) for clarification
What I've tried
A failed workaround
A crappy, unsound workaround
Hi Jens, Jack and List Participants,
Thanks, Jens, for your reply.
On 4/5/08, Jens Alfke wrote:
Cannot remove an observer <NSTableBinder 0x158a70> for the key
path "name" from <Alternative 0x15abd0> because it is not
registered as an observer.
"It" refers to the observer. -removeObserver:forKeyPath: raises this
exception if told to remove an object that isn't currently registered
as an observer. So what's happening is that a table view is trying to
unregister as an observer from one of your objects that it
unfortunately didn't previouly register as an observer for.
The usual cause of this is that you have a property that isn't KVO-compliant.
All my properties have a setters and getters and have the
appropriate calls to
will|did Access|Change ValueForKey
before/after any change. Is there more that I need to do?
For what its worth, let me explain exactly what is causing the problem.
Firstly, the 'Contribution' Entity is more-or-less a many to
many join table (but with a 'degree' attribute) between
'Alternatives' and 'Values'.
I have a simple but unusual arrangement of what is displayed in
the 'degree' column of my 'Alternatives' tableView. Depending
on the selection in a 'Values' tableView, I show the 'degree'
attribute of a certain set of 'Contribution' objects (basically,
the related 'Contributions' of the selected 'Value' -- there
will be one for each 'Alternative'). i.e. Every time the user
changes the 'Values' table selection, the degree column of the
Alternatives' tableView changes to show the 'degree' attributes
of a new set of 'Contributions'. That change causes the "cannot
remove an observer" exceptions.
Simple idea, hard to explain. It could more easily have been a
very wide tableView with a column for each 'Contribution', the
column label being the name of the relevant 'Value'. The
current technique avoids at least three undesirable aspects:
variable number of table columns,
truncated column labels,
horizontal scrolling.
Those undesirables will be even more so when the app is also a
web app.
Something accesses your 'foo' property and registers as an observer of
that property, and also as an observer of the object that's the
property's current value;
Jens, can you please elaborate on that distinction? I was not
aware that something could be an observer of an object.
you change the value of 'foo' without letting anyone know; the
observer then later decides to stop observing, gets your 'foo'
property, and removes itself as an observer of that object. But it's
no longer the same object that it registered as an observer for...
OK. I made a guess that the culprit was ether the 'Alternative'
tableView or the 'Alternative' ArrayController. So, in my
WindowController's awakeFromNib, I tried adding them as
observers for the 'degree' property (the one the exception
complains about) for all 'Contribution' objects, like so:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity: [NSEntityDescription
entityForName: @"Contribution"
inManagedObjectContext: [self managedObjectContext]]];
NSArray *contributions = [[self managedObjectContext]
executeFetchRequest: fetchRequest error: &error];
[fetchRequest release];
for (Contribution *aContribution in contributions)
{
[aContribution addObserver: alternativeTableView
forKeyPath: @"degree"
options:
(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context: NULL];
[aContribution addObserver: alternatives
forKeyPath: @"degree"
options:
(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld)
context: NULL];
}
It didn't help. Either the addObserver is insufficient or I
still don't know what the "it" is in the error message. (Or,
I've created over-observance as mentioned by Jack.)
In desperation, I added try-catch around each step of the code
that throws exceptions and discovered that these two lines throw :
[selectedAlternative
setContributionForSelectedDecisionValue: nil]; // KVO dummy setter
[alternativeArrayController rearrangeObjects];
but this line doesn't throw
[alternativeTableView reloadData];
In the short-term, I've caught the two exceptions -- that has
allowed the application to more-or-less work. But it doesn't
bode well for the future. For one thing, any subsequent
[alternativeArrayController rearrangeObjects] will fail.
I know of at least two other people struggling with this problem
and have seen others encounter it in the past. It would be
great to have an answer here in the list archives.
Thanks,
Steve
_______________________________________________
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