• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: performSelector:withObject fails with class object
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: performSelector:withObject fails with class object


  • Subject: Re: performSelector:withObject fails with class object
  • From: Tron Thomas <email@hidden>
  • Date: Sat, 07 Feb 2009 08:44:30 -0800

Greg Parker wrote:
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.



I thought about trying NSObject after I posted the mailing list. The main reason I went with Object originally was because I just wanted to write something quick and simple. I did not want to worry about linking to the entire Cocoa framework and have to create an auto-release pool. However, I just configured everything to use garbage collection and that helped to keep things simple enough to still use NSObject.

I originally was trying to use objc_getClass instead of objc_getMetaClass. It did not seem to be working. Maybe this was because I was hitting the NSInvocation warnings which would have happened anyway, since I was using Object instead of NSObject.

Anyway, I switched to using NSClassFromString as suggested by Ken and everything is working now.


_______________________________________________

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


  • Follow-Ups:
    • Re: performSelector:withObject fails with class object
      • From: Michael Ash <email@hidden>
References: 
 >performSelector:withObject fails with class object (From: Tron Thomas <email@hidden>)
 >Re: performSelector:withObject fails with class object (From: Greg Parker <email@hidden>)

  • Prev by Date: name == "$FETCH_SOURCE.name" -- Doesn't find dupes?
  • Next by Date: Re: Read lines from very large text file
  • Previous by thread: Re: performSelector:withObject fails with class object
  • Next by thread: Re: performSelector:withObject fails with class object
  • Index(es):
    • Date
    • Thread