PDA

View Full Version : KVO: observing self crashes Xcode




MrFusion
Mar 3, 2012, 01:38 PM
I picked up programming with cocoa again but I am getting an unexpected crash. Even Xcode crashes on this sometimes.
This code is part of a CATextLayer subclass. I want to observe when changes happen to the layer. The app crashes when observing fontSize and foregroundColor, but not for string and font. The crash occurs in dealloc.
Aren't you supposed to observe self with self?
Why is the layer even being dealloc'ed?


-(id) init
{
self = [super init];
if (self)
{
#if 1
//observers
for (NSString *keyPath in [NSArray arrayWithObjects:@"string",@"font",@"fontSize",@"foregroundColor", nil])
{
[self addObserver:self
forKeyPath:keyPath
options:NSKeyValueObservingOptionNew
context:NULL];
}
#endif
}
return self;
}

-(void) dealloc
{
#if 0
#warning xcode crash!!!!!
for (NSString *keyPath in [NSArray arrayWithObjects:@"string",@"font",@"fontSize",@"foregroundColor", nil])
{
[self removeObserver:self
forKeyPath:keyPath
context:NULL];
}
#endif
[super dealloc];
}


This code will crash it.

-(IBAction) test:(id)sender
{
[myTextLayer setString:[textField stringValue]]; //works ok
[myTextLayer setFont:[NSFont fontWithName:@"Verdana"
size:48]]; //works ok

// [myTextLayer setFontSize:11]; //crash
// [myTextLayer setForegroundColor:[[NSColor blackColor] CGColor]] ;//crash
}



gnasher729
Mar 3, 2012, 01:58 PM
Look for the documentation of the method removeObserver:forKeyPath:context:

What do you find?

I'd suggest you learn how to turn on warnings in your code. With appropriate build settings, this code wouldn't have compiled. If you saw warnings and ignored them, shame on you.

MrFusion
Mar 4, 2012, 04:18 AM
Look for the documentation of the method removeObserver:forKeyPath:context:

What do you find?

I'd suggest you learn how to turn on warnings in your code. With appropriate build settings, this code wouldn't have compiled. If you saw warnings and ignored them, shame on you.

Using the standard settings, I get plenty of warnings. But not on this piece of code.

So, I should fill something in on context.

gnasher729
Mar 4, 2012, 07:07 AM
Using the standard settings, I get plenty of warnings. But not on this piece of code.

So, I should fill something in on context.

For heaven's sake. Did you find any documentation for that method? No, you didn't. Why didn't you? Because it doesn't exist. You'll get a warning "Instance method not found". When you run it, you get a crash, and XCode tells you exactly the same thing at runtime. The method is removeObserver:forKeyPath: Not removeObserver:forKeyPath:context:

Do yourself a real favour and change your code so that there are no warnings. Warnings are there for a reason. It's the compiler saying "you are doing something that isn't illegal according to the language specification, but most probably rather stupid.". You just wasted a day looking for a bug that in my setup wouldn't have compiled in the first place and would have taken five seconds to find.

MrFusion
Mar 4, 2012, 07:41 AM
For heaven's sake. Did you find any documentation for that method? No, you didn't. Why didn't you? Because it doesn't exist. You'll get a warning "Instance method not found". When you run it, you get a crash, and XCode tells you exactly the same thing at runtime. The method is removeObserver:forKeyPath: Not removeObserver:forKeyPath:context:

Do yourself a real favour and change your code so that there are no warnings. Warnings are there for a reason. It's the compiler saying "you are doing something that isn't illegal according to the language specification, but most probably rather stupid.". You just wasted a day looking for a bug that in my setup wouldn't have compiled in the first place and would have taken five seconds to find.

From NSKeyValueObserving Protocol Reference
(informal protocol)


removeObserver:forKeyPath:context:
Stops a given object from receiving change notifications for the property specified by a given key-path relative to the receiver and a context.

- (void)removeObserver:(NSObject *)observer forKeyPath :(NSString *)keyPath context:(void *)context
Parameters
observer
The object to remove as an observer.
keyPath
A key-path, relative to the receiver, for which anObserver is registered to receive KVO change notifications.
context
Arbitrary data that more specifically identifies the observer to be removed.
Discussion
Examining the value in context you are able to determine precisely which addObserver:forKeyPath:options:context: invocation was used to create the observation relationship. When the same observer is registered for the same key-path multiple times, but with different context pointers, an application can determine specifically which object to stop observing.

Availability
Available in Mac OS X v10.7 and later.
Declared In
NSKeyValueObserving.h