Re: Console: *** -observeValueForKeyPath:... only defined for abstract class
Re: Console: *** -observeValueForKeyPath:... only defined for abstract class
- Subject: Re: Console: *** -observeValueForKeyPath:... only defined for abstract class
- From: Jerry Krinock <email@hidden>
- Date: Tue, 25 Sep 2007 17:34:02 -0700
On 2007 Sep, 24, at 2:04, Thomas Engelmeier wrote:
Without going into detail for your specific problem, I'd try to
break when that message is output and then inspect which object
outputs the message....If you are lucky, a breakpoint on
[NSException raise] or NSLog will work.
If the error does not occur 100% reproducible, it might be bad
memory management - an object deallocated and in the same memory
location repalced with something completely different, whose method
is invoked.
Thank you, Thomas. Further testing confirmed that it is not 100%
reproducible. Besides NSKeyValueObservance, sometimes the errant
message gets sent to an NSIdEnumerator and sometimes
objc_message_send crashes. So, yes, it looks like a case of invalid
message receiver.
To troubleshoot this, I defined observeValueForKeyPath:::: in a
category on NSObject, so that way any time that message was sent to
an object which didn't handle it, I'd get a log.
I've pasted in a typical log below. Indeed, the "changing" 'object'
is one of my NSManagedObjects, and the 'change' is the change I had
just made. But there are two things I find surprising:
(a) The observationInfo of the observed object lists three
observers. The last two are ones that I added. They are still
valid. But the first one is a mysterious
NSKeyValueObservationForwarder. Does that give anyone a clue?
(b) However, the object receiving this observeValueForKeyPath::::
message is not even one of those three observers. How it receiving
this message? (Possible unhelpful answer: because it was forwarded
by that "...Forwarder" thingey.)
I've searched my code several times for addObserver::: and bind::::
messages, but the only invocations I can find on objects of this
class ('Entry') are the two which are causing the two expected
observers I see in the observationInfo.
Jerry
*****************************************************
Typical log "catch" (abridged to improve readability)
*****************************************************
Internal Error!!! Stray observation message received!!
self = NSIdEnumerator 3261b0 <NSIdEnumerator: 0x3261b0>
keyPath = swimmer
object = Entry 330130 Entry at position 4 in 800 Free for Caroline
change = {
kind = 1;
new = <Swimmer: 0x32bf30> (
entity: Swimmer;
id: 0x32bf60 <x-coredata:///Swimmer/tblahblahUUID> ;
data: {
entries = (0x325c00 <x-coredata:///Entry/
tblahblahUUID>);
name = fishc;
}
);
old = <null>;
}
context = 3261b0
infoString = <NSKeyValueObservance:
Observer: 0x14a06770,
Key path: swimmer,
Include old: YES,
Include new: YES,
Context: 0x14a06770,
Property: 0x33b3a0>,
observer is: <NSKeyValueObservationForwarder>
<NSKeyValueObservationForwarder: 0x14a06770>
infoString = <NSKeyValueObservance:
Observer: 0x394740,
Key path: swimmer.name,
Include old: NO,
Include new: NO,
Context: 0x892,
Property: 0x34c980>,
observer is: <TextFieldListView> <TextFieldListView: 0x394740>
infoString = <NSKeyValueObservance:
Observer: 0x394740,
Key path: position,
Include old: NO,
Include new: NO,
Context: 0x892,
Property: 0x323c90>
observer is: <TextFieldListView> <TextFieldListView: 0x394740>
***********************
Code producing that log
***********************
@interface NSObject (JerryDebug)
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context ;
@end
@implementation NSObject (JerryDebug)
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSLog(@"Internal Error!!! Stray observation message received!!") ;
NSLog(@"self = %@ %x %@", [self class], self, self) ;
NSLog(@"keyPath = %@", keyPath) ;
NSLog(@"object = %@ %x %@", [object class], object, object) ;
NSLog(@"change = %@", change) ;
NSLog(@"context = %x", context) ;
NSArray* observationInfos = [object observationInfo] ;
NSDictionary* info ;
NSEnumerator* e = [observationInfos objectEnumerator] ;
while((info = [e nextObject])) {
NSString* infoString = [info description] ;
NSLog(@"infoString = %@", infoString) ;
NSScanner* scanner = [[NSScanner alloc]
initWithString:infoString] ;
[scanner scanUpToString:@": 0x" intoString:NULL] ;
[scanner scanString:@": 0x" intoString:NULL] ;
NSString* hexAddressString ;
[scanner scanUpToString:@"," intoString:&hexAddressString] ;
[scanner release] ;
const char* hexAddressC = [hexAddressString UTF8String] ;
long hexAddress ;
sscanf(hexAddressC, "%x", &hexAddress) ;
id observer = (id)hexAddress ;
NSLog(@"observer is: <%@> %@", [observer class], observer) ;
}
NSBeep() ;
}
@end
_______________________________________________
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