I have code distributed in a library which looks like this:
if ([[NSString class] instancesRespondToSelector: @selector(JSONValue)]) {
NSString *jsonString = [[[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding] autorelease];
dict = [jsonString performSelector: @selector(JSONValue)];
}
For some reason a -[__NSCFString JSONValue]: unrecognized selector sent to instance
exception is getting thrown when the performSelector:
method gets called. This is code that is distributed in a library that I wrote, but I can't reproduce or debug it myself. Instead a third-party is reporting this problem. Under what conditions could instancesRespondToSelector:
while actually calling the method using performSelector:
throw an exception?
edit There is a case which could explain why this occurs, but it doesn't make sense. If the developers were to do something like this:
@implementation NSString (OurHappyCategory)
+ (BOOL)instancesRespondToSelector:(SEL)aSelector
{
return YES;
}
@end
It would explain why the code is executing, but it would of course be a very bad thing to do. Is there a way this problem could occur that makes sense?
NSString is basically a class cluster, and brings up all sorts of complications... you actually need to ask the instance if it responds to the selector.
NSString *jsonString = [[[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding] autorelease];
if ([jsonString respondsToSelector: @selector(JSONValue)]) {
dict = [jsonString performSelector: @selector(JSONValue)];
}
but your problem probably has to do with compiling or linking the extension... if the category is added in a library then you will need to sprinkle in the -ObjC
linker flag.
EDIT:
I have been working a little bit on reproducing this issue... which I am unable to...
do you have any more information.. for example is the failure only occurring on the simulator, or just on device, iOS 4.x, GNU linker vs LLDB's linker, ABI/Runtime differences?
I guess that you didn't import a third party library in a correct way. Usually this methods are added as category to NSString, it happened to me that I could see the .h file but the .m wasn't compiled. You can check it inside xcode target-->build phases-->compile sources. Or check if you aheve this flag inside Project-->Build Settings-->Other linker flag = -all_load
The exception does not come directly from the Objective-C runtime in response to sending a message that the instance doesn't recognize. It comes from -[NSObject doesNotRecognizeSelector:]
, which is invoked at the end of various method lookup and forwarding mechanisms.
However, anything can invoke -doesNotRecognizeSelector:
when it wants. A class can "disavow" an inherited method by overriding it and making the override just invoke -doesNotRecognizeSelector:
. As documented, this will result in the exception you're seeing in spite of the fact that -respondsToSelector:
(and +instancesRespondToSelector:
) returning YES
.
I couldn't tell you why __NSCFString
is doing that in your end user's case. Is the app which is using your library using categories or method swizzling to modify the methods on that class?
Also, does your logging show the actual stack trace capture in the exception? That might be informative.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With