Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I invoke a class method by NSInvocation?

Tags:

objective-c

We can get NSMethodSignature by + (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector of NSObject. Then construct NSInvocation by + (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)signature

Here is the problem. We can only get the method signature of instance,how about the class method?

like image 504
Fang Yang Avatar asked Jun 05 '12 15:06

Fang Yang


2 Answers

You can get the class methods by:

NSMethodSignature *pMS = [[YourObject class] methodSignatureForSelector: (SEL)aSelector];

The fragment [YourObject class] returns an instance of the class object (singleton) which you can then use to get class methods.

ADD: New info from comments below. You can just do the following:

NSMethodSignature *pMS = [YourObject methodSignatureForSelector: (SEL)aSelector];
like image 51
Kent Avatar answered Nov 15 '22 07:11

Kent


Here is additional detail about invoking class (and instance methods) via NSInvocation showing methodForSignature: and instanceMethodForSignature:

@interface SomeObject : NSObject
+ (void)instanceAndClass;
- (void)instanceAndClass;
+ (void)classOnly;
- (void)instanceOnly;
@end

@implementation SomeObject
+ (void)instanceAndClass { NSLog(@"Class version"); }
- (void)instanceAndClass { NSLog(@"Instance version"); }    
+ (void)classOnly { NSLog(@"Class only"); }
- (void)instanceOnly { NSLog(@"Instance only"); }
@end

@implementation Foo

- (void)invoke:(id)receiver signature:(NSMethodSignature *)signature selector:(SEL)selector {
    if (!signature) {
        NSLog(@"method signature is nil");
        return;
    }        
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    invocation.selector = selector;
    invocation.target = receiver;
    [invocation invoke];
}

- (void)foo {
    NSMethodSignature *signature;
    SomeObject *someObject = [SomeObject new];

    signature = [someObject methodSignatureForSelector:@selector(instanceAndClass)];
    [self invoke:someObject signature:signature selector:@selector(instanceAndClass)];
    // 2015-07-10 11:01:10.227 FooBar[65312:3097866] Instance version
    [self invoke:[someObject class] signature:signature selector:@selector(instanceAndClass)];
    // 2015-07-10 11:01:10.227 FooBar[65312:3097866] Class version

    signature = [someObject methodSignatureForSelector:@selector(classOnly)];
    [self invoke:someObject signature:signature selector:@selector(classOnly)];
    // 2015-07-10 11:01:10.227 FooBar[65312:3097866] method signature is nil

    signature = [[someObject class] methodSignatureForSelector:@selector(classOnly)];
    [self invoke:[someObject class] signature:signature selector:@selector(classOnly)];
    // 2015-07-10 11:01:10.228 FooBar[65312:3097866] Class only

    signature = [someObject methodSignatureForSelector:@selector(instanceOnly)];
    [self invoke:someObject signature:signature selector:@selector(instanceOnly)];
    // 2015-07-10 11:01:10.228 FooBar[65312:3097866] Instance only

    signature = [[someObject class] methodSignatureForSelector:@selector(instanceOnly)];
    [self invoke:[someObject class] signature:signature selector:@selector(instanceOnly)];
    2015-07-10 11:01:10.228 FooBar[65312:3097866] method signature is nil

    signature = [[someObject class] instanceMethodSignatureForSelector:@selector(instanceOnly)];
    [self invoke:someObject signature:signature selector:@selector(instanceOnly)];
    // 2015-07-10 11:01:10.228 FooBar[65312:3097866] Instance only
}
like image 26
Ben Flynn Avatar answered Nov 15 '22 06:11

Ben Flynn