KVO: observing self crashes Xcode

Discussion in 'Mac Programming' started by MrFusion, Mar 3, 2012.

  1. macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #1
    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?

    Code:
    -(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.
    Code:
    -(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
    }	
    
     
  2. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    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.
     
  3. thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #3
    Using the standard settings, I get plenty of warnings. But not on this piece of code.

    So, I should fill something in on context.
     
  4. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    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.
     
  5. MrFusion, Mar 4, 2012
    Last edited: Mar 7, 2012

    thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #5
    From NSKeyValueObserving Protocol Reference
    (informal protocol)

    Code:
    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
    
     

Share This Page