Re: KVO can be unsafe in -init?
Re: KVO can be unsafe in -init?
- Subject: Re: KVO can be unsafe in -init?
- From: John Chang <email@hidden>
- Date: Wed, 9 Sep 2009 11:02:40 +0200
On 9 sep 2009, at 04.51, Graham Cox wrote:
Because you're trying to use a nil key with a dictionary. Why not
set a breakpoint on objc_exception_throw and see where that is being
attempted?
Because it's happening for some users and not in-house :)
On 9 sep 2009, at 05.02, Ken Ferry wrote:
Is your -observeValueForKeyPath: safe to be called with a partially
set up object?
I don't think we're getting that far. (See below)
Do you have any subclasses of your object? If so, -
observeValueForKeyPath: is getting called on them before they've
done their work in init.
No, it's a singleton. Basically it's a "manager" object that wants to
continually monitor something else for changes. Also, -addObserver is
the last line of code in -init, before the return.
On 9 sep 2009, at 05.03, Roland King wrote:
One thing to note, you're using a context of NULL, which I used to
do all the time until I got badly bitten.
What would you recommend using as the context? I'm used to checking
object/keyPath, though I noticed as you pointed out that the Xcode
template does it with context.
On 9 sep 2009, at 05.09, Stephen J. Butler wrote:
Why do you think registering the observer is causing this exception?
There's nothing KVO related in this message.
Sorry, I was thinking of including the backtrace and I guess I didn't.
In -init, -addObserver: is only called once, so we're pretty certain
about the exact line of code that is being indicated here, unless the
stack is lying.
Thread 0 Crashed:
0 libSystem.B.dylib 0x31dd594c __kill + 8
1 libSystem.B.dylib 0x31dd593a kill + 4
2 libSystem.B.dylib 0x31dd592e raise + 10
3 libSystem.B.dylib 0x31deccf8 abort + 36
4 libstdc++.6.dylib 0x374ef840
__gnu_cxx::__verbose_terminate_handler() + 588
5 libobjc.A.dylib 0x300166b8 _objc_terminate + 160
6 libstdc++.6.dylib 0x374ecf34 __cxxabiv1::__terminate
(void (*)()) + 76
7 libstdc++.6.dylib 0x374ecfac std::terminate() + 16
8 libstdc++.6.dylib 0x374ed060 __cxa_rethrow + 108
9 libobjc.A.dylib 0x30016554 objc_exception_rethrow + 4
10 Foundation 0x305049f6 -[NSObject
(NSKeyValueObserverRegistration)
addObserver:forKeyPath:options:context:] + 342
11 FooApp -[XYZManager init] (in FooApp) +
548 0x10000000 + 375876
12 FooApp +[XYZManager sharedManager] (in
FooApp) + 124 0x10000000 + 379580
Sun Sep 6 13:41:26 unknown FooApp[1609] <Error>: *** Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason: '*** -
[NSCFDictionary setObject:forKey:]: attempt to insert nil key'
- (id)init
{
if ((self = [super init]))
{
_foo = [[NSMutableDictionary alloc] init];
_bar = [[NSMutableDictionary alloc] init];
[[XYZManager sharedManager] addObserver:self forKeyPath:@"allObjects"
options:NSKeyValueObservingOptionInitial context:NULL];
}
return self;
}
///
What I'm hearing from the various responses is that as a rule, it's
not safe to expose self at all during initialization, which makes
sense, though in this case, we're stumped as to why it blows up, since
by the time we call -addObserver:, self is already valid. In the
interim, we're just going to catch that exception. But it's worrisome
that we don't understand the root cause. We're thinking of refactoring
this class in the future anyway, so this problem could magically go
away. Maybe we can just chalk it up to KVO voodoo.
Thanks for the responses,
/John
_______________________________________________
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