Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically invoke a class method in Objective C

Suppose I have Objective C interface SomeClass which has a class method called someMethod:

@interface SomeClass : NSObject {
}

+ (id)someMethod;
@end

In some other interface I want to have a helper method that would dynamically invoke someMethod on a class like this:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

What should be the implementation for invokeSelector? Is it possible at all?

- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
   // ???
}
like image 476
GregK Avatar asked Nov 23 '09 04:11

GregK


4 Answers

Instead of:

[someOtherObject invokeSelector:@selector(someMethod) forClass:[SomeClass class];

call:

[[SomeClass class] performSelector:@selector(someMethod)];

Example (using GNUstep ...)

file A.h

#import <Foundation/Foundation.h>
@interface A : NSObject {}

- (NSString *)description;
+ (NSString *)action;
@end

file A.m

#import <Foundation/Foundation.h>
#import "A.h"

@implementation A

- (NSString *)description
{
    return [NSString stringWithString: @"A"];
}

+ (NSString *)action
{
    return [NSString stringWithString:@"A::action"];
}

@end

Somewhere else:

A *a = [[A class] performSelector:@selector(action)];
NSLog(@"%@",a);

Output:

2009-11-22 23:32:41.974 abc[3200] A::action

nice explanation from http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html:

"In Objective-C, a class object gets all the instance methods of the root class for its hierarchy. This means that every class object that descends from NSObject gets all of NSObject's instance methods - including performSelector:."

like image 199
stefanB Avatar answered Nov 11 '22 21:11

stefanB


In Objective-C, classes are objects as well. The class objects are treated differently, however, as they can call the instance methods of their root class (NSObject or NSProxy in Cocoa).

So it's possible to use all the instance methods defined in NSObject on class objects as well and the right way to dynamically invoke a class method is:

[aClass performSelector:@selector(aSelector)];

The apple docs are a bit more specific.

like image 36
Adrian Avatar answered Nov 11 '22 21:11

Adrian


You shouldn't implement this yourself.

The NSObject Protocol has a performSelector: method that does exactly this.

like image 2
Ben S Avatar answered Nov 11 '22 19:11

Ben S


Is this built-in method what you want?

id objc_msgSend(id theReceiver, SEL theSelector, ...)

(See the runtime reference docs for this function.)

like image 2
vanja. Avatar answered Nov 11 '22 19:11

vanja.