Cocoa bug? release/removeObserver from inside observeValueForKeyPath
Cocoa bug? release/removeObserver from inside observeValueForKeyPath
- Subject: Cocoa bug? release/removeObserver from inside observeValueForKeyPath
- From: Geoff Schmidt <email@hidden>
- Date: Thu, 29 May 2008 15:15:14 -0700
Suppose that two objects A and B are observing a key on a third
object C. Suppose further that from its observeValueForKeyPath
method, A releases B, causing B's dealloc method to be called, and
that B's dealloc method properly calls removeObserver. Then, despite
the call to removeObserver, it looks like Cocoa tries to call
observeValueForKeyPath on B anyway, which is a call off into empty
space.
This is on 10.4.11.
1) Am I doing something wrong?
2) Is this documented somewhere? (I didn't find it anywhere)
3) If this is already known, is there a customary pattern for
avoiding the problem? "Never release from observeValueForKeyPath" is
a bit harsh!
Test code at end. To use, make MainMenu.nib instantiate the object
'test', and make a window with a checkbox bound to values.testkey on
UserDefaultsController. Check the box. Here is the result if this is
done with NSZombieEnabled=YES:
2008-05-29 14:57:23.148 testcase[8682] helper init
2008-05-29 14:57:25.869 testcase[8682] test observe
2008-05-29 14:57:25.869 testcase[8682] helper dealloc
2008-05-29 14:57:25.876 testcase[8682] *** -[_NSZombie forward::] not
overridden!
thanks for any pointers,
Geoff
[snip]
#import <Cocoa/Cocoa.h>
/// interfaces
@interface helper : NSObject { }
@end
@interface test : NSObject {
id obj;
}
@end
/// helper implementation
@implementation helper
- (id)init {
[[NSUserDefaultsController sharedUserDefaultsController]
addObserver:self
forKeyPath:@"values.testkey"
options:NSKeyValueObservingOptionNew
context:NULL];
NSLog(@"helper init");
return [super init];
}
- (void)dealloc {
[[NSUserDefaultsController sharedUserDefaultsController]
removeObserver:self
forKeyPath:@"values.testkey"];
NSLog(@"helper dealloc");
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSLog(@"helper observe");
}
@end
/// test implementation
@implementation test
- (void)awakeFromNib {
[[NSUserDefaultsController sharedUserDefaultsController]
addObserver:self
forKeyPath:@"values.testkey"
options:NSKeyValueObservingOptionNew
context:NULL];
obj = [[helper alloc] init];
}
- (void)dealloc {
NSLog(@"test dealloc");
[[NSUserDefaultsController sharedUserDefaultsController]
removeObserver:self
forKeyPath:@"values.testkey"];
[obj release];
obj = nil;
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSLog(@"test observe");
[obj release];
obj = nil;
}
@end
// (end of file)
_______________________________________________
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