Re: performSelector:withObject fails with class object
Re: performSelector:withObject fails with class object
- Subject: Re: performSelector:withObject fails with class object
- From: Greg Parker <email@hidden>
- Date: Thu, 5 Feb 2009 22:23:33 -0800
On Feb 5, 2009, at 9:50 PM, Tron Thomas wrote:
I have a couple of classes that are delcared like this:
#import <objc/objc.h>
#import <objc/Object.h>
@interface SomeClass : Object
{
@private
// Instance data members ...
}
+ (SomeClass*)instanceFromData:(id)data;
// Other methods ...
@end
Class Object is dead. Don't use it. Use NSObject instead.
In yet another class, I have this function:
+ (id)createInstanceForClass:
(const char*)className
withData:(id)data
{
id metaClass = ::objc_getMetaClass(className);
if(nil == metaClass){
return nil;
}
unsigned int count;
Method* method = ::class_copyMethodList(metaClass, &count);
for(unsigned int index = 0; index < count; ++index){
std::clog << ::sel_getName(::method_getName(method[index])) <<
std::endl;
}
return [metaClass performSelector:@selector(instanceFromData:)
withObject:data];
}
When the middle section of the function containing the
class_copyMethodList is simply meant for verification, and prints:
instanceFromData
when the class name for either of the first two classes is
provided. This seems to indicate the proper class object is being
used and the expectation is that the call to
performSelector:withObject: should succeed.
Your introspection of the metaclass's method list shows what messages
the class object will respond to. But then you send instanceFromData:
to the metaclass object, not the class object. The metaclass doesn't
respond to instanceFromData:, so it blows up.
(Instances respond to messages from their class's method list. Classes
respond to messages from their metaclass's method list. Metaclasses
respond to messages from the metaclass's metaclass's method list,
which is the root metaclass's method list. If you don't understand
that third sentence, don't worry; in practice you only care about the
first two.)
If you want to call the class method +[SomeClass instanceFromData:],
do this instead:
const char *className = "SomeClass";
id cls = ::objc_getClass(className);
return [cls performSelector:@selector(instanceFromData:)
withObject:data];
Or you can skip performSelector:withData: entirely. It's intended for
code where the selector is not known at compile time. Since you know
the selector, just use it directly:
const char *className = "SomeClass";
id cls = ::objc_getClass(className);
return [cls instanceFromData:data];
However, when the performSelector:withObject: is executed, output
like the following is logged, and the program traps in the debugger:
*** NSInvocation: warning: object 0x1b0dc of class 'Object' does not
implement methodSignatureForSelector: -- trouble ahead
*** NSInvocation: warning: object 0x1b0dc of class 'Object' does not
implement doesNotRecognizeSelector: -- abort
These ugly errors arise because you're using class Object instead of
class NSObject. Class Object is dead.
--
Greg Parker email@hidden Runtime Wrangler
_______________________________________________
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