如何通过NSInvocation调用类方法?

6
我们可以通过调用NSObject+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector方法来获取NSMethodSignature。然后使用+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)signature构建NSInvocation。但问题在于,我们只能获取实例方法的方法签名,那么类方法怎么办呢?
2个回答

7

您可以通过以下步骤获取类方法:

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

[YourObject class]片段返回一个类对象(单例),您可以使用该对象来获取类方法。

补充:以下是评论中的新信息。您可以直接执行以下操作:

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

1
你甚至不需要 class 部分。你可以直接将它发送到 YourObject,它仍然可以工作,因为类名也是一等对象,同时也是 typedefs。 - Richard J. Ross III
谢谢!但是这只适用于声明为实例方法的方法,该方法由“-”启动。我无法获取声明为类方法的methodSignature,该方法由“+”启动。 - Fang Yang
4
不正确。有两种不同的方法:instanceMethodSignatureForSelector:methodSignatureForSelector:。一个用于实例方法,另一个用于类方法。 - Kent
ADD 部分不正确,请参考 @Ben Flynn 的测试代码。 - xi.lin

4

这里提供有关通过NSInvocation调用类(和实例)方法的额外细节,展示了methodForSignature: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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接