Re: Debugging "attempt to insert nil value" on customer's machine
Re: Debugging "attempt to insert nil value" on customer's machine
- Subject: Re: Debugging "attempt to insert nil value" on customer's machine
- From: Ondra Cada <email@hidden>
- Date: Tue, 14 Sep 2004 15:28:52 +0200
Gideon,
On 14.9.2004, at 11:40, Gideon King wrote:
Due to the fact that a class cluster is used, I can't do anything with
NSMutableDictionary itself. The concrete class that is identified in
the error is a subclass of NSMutableDictionary called NSCFDictionary.
This is a private class, so I used class dump to get the interface and
subclassed it and used poseAsClass to try to use my own class, which
has its own version of setObject:forKey:
My subclass method never gets called, even if I put the poseAsClass:
before NSApplicationMain();
try +load, that's as soon as reasonably possible.
The exception message does change though to:
*** -[%NSCFDictionary setObject:forKey:]: attempt to insert nil value
(notice the %) leading me to believe that the runtime system does know
something about the posed class. It therefore appears that there is
something going on behind the scenes here, which I don't understand.
Me neither, but I *suspect* (really do *not* know) those CoreFoundation
"toll-free bridged" uglies are not quite ObjC classes and just don't
support poseAsClassing (and more) properly. At least, they did bring
havoc to the mutability concept and class distinctions, and it is quite
plausible suspection they broke much more :(((
This solution is the one suggested in the archives, but doesn't work
for me, and the person who originally suggested it no longer recalls
how he got it to work.
I would welcome any suggestions of ways to implement something that
will allow me to log the information that will allow me to find and
fix the problem.
One possible thing might be to mess directly with the runtime
structures (i.e., to change the appropriate method_imp). Here's the
generic method to do so:
+(IMP)replaceSelector:(SEL)oldSel ofClass:(Class)oldCl by:(SEL)newSel
ofClass:(Class)newCl {
void _objc_flush_caches(Class); // get rid of the warning
IMP original=[oldCl instanceMethodForSelector:oldSel]; // original
to remember
if (!original) {
[self logFail:@"cannot find implementation for '%@' in
%@",NSStringFromSelector(oldSel),NSStringFromClass(oldCl)];
return NULL;
}
struct objc_method *method=class_getInstanceMethod(oldCl,oldSel);
// original to change
if (!method) {
[self logFail:@"cannot find method for '%@' in
%@",NSStringFromSelector(oldSel),NSStringFromClass(oldCl)];
return NULL;
}
IMP new=[newCl instanceMethodForSelector:newSel]; // new method to
use
if (!new) {
[self logFail:@"cannot find implementation for '%@' in
%@",NSStringFromSelector(newSel),NSStringFromClass(newCl)];
return NULL;
}
method->method_imp=new;
_objc_flush_caches(oldCl);
return original;
}
That well might fail with CF-thingies too, though. If so, well... do
you happen to know which method is used to create the dictionary in
question? If so, you can replace the dictionary by your own subclass on
the decent ObjC level, without having to dive into the CoreFoundation
swamp:
@implementation PosedAsDictionary:NSMutableDictionary
-(NSMutableDictionary*)dictionary { // or another method
return [[[MyOwnDictionary alloc] init] autorelease];
}
+(void)load {
[self poseAsClass:[self superclass]];
}
@end
@interface MyOwnDictionary:NSMutableDictionary {
NSMutableDictionary *md;
}
@end
@implementation MyOwnDictionary
-(void)setObject:o forKey:key {
if (!o || !key) WHATEVER...
[super setObject:o forKey:key];
}
-(unsigned)count {return [md count];}
-objectForKey:k {return [md objectForKey:k];}
-(NSEnumerator*)keyEnumerator {return [md keyEnumerator];}
-(void)setObject:o forKey:k {
if (!md) md=[[NSMutableDictionary alloc] init];
[md setObject:o forKey:k];
}
-(void)removeObjectForKey:k {[md removeObjectForKey:k];}
-(void)dealloc {
[md release];
[super dealloc];
}
@end
If this does not help either, sorry: no more ideas at the moment...
---
Ondra Čada
OCSoftware: email@hidden http://www.ocs.cz
private email@hidden http://www.ocs.cz/oc
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden