0

我正在使用forwardInvocation:objective-c 的功能,我需要知道该方法收到的参数类型。在我的示例中,我传递了它,intgetArgumentTypeAtIndex:告诉我它是一个id。这是一个简单的例子:

@interface Do : NSObject
+ (void) stuff:(int)x;
@end
@implementation Do
+ (NSMethodSignature *) methodSignatureForSelector:(SEL)selector
{
    NSMethodSignature* signature = [super methodSignatureForSelector:selector];
    if (!signature)
        signature = [self methodSignatureForSelector:@selector(forwardInvocation:)];
    return signature;
}

+ (void)forwardInvocation:(NSInvocation *)i
{
    const char* argType = [i.methodSignature getArgumentTypeAtIndex:2];
    NSLog(@"%s == %s", argType, @encode(id)); // @ == @
    NSLog(@"%s == %s", argType, @encode(int)); // @ == i
}
@end

我是这样称呼它的:

[Do stuff:123];

知道为什么我没有得到id而不是int作为类型吗?

4

2 回答 2

4

stuff:问题是您实际上在该类上没有方法,因此methodSignatureForSelector:将返回nil-看起来您发现了这一点并因此实现了自己的版本,但是super调用失败了,因此最终返回了签名forwardInvocation:-即不是你想要的!

要解决这个问题,您要么需要将 定向methodSignatureForSelector:到具有选择器的类,要么使用协议 - 如果一个类实现了协议,那么它将返回该协议中任何方法的签名,即使这些方法实际上并未由那堂课。

这是您使用协议的示例:

@protocol DoProtocol
@optional
+ (void) stuff:(int)x;
@end

@interface Do : NSObject<DoProtocol>
@end

@implementation Do

+ (void)forwardInvocation:(NSInvocation *)i
{
   const char* argType = [i.methodSignature getArgumentTypeAtIndex:2];
   NSLog(@"%s == %s", argType, @encode(id)); // @ == @
   NSLog(@"%s == %s", argType, @encode(int)); // @ == i
}

@end

避免了未实现方法的@optional任何编译器警告。methodSignatureForSelector:(from )的默认实现NSObject将返回从协议获得的有效签名,因此forwardInvocation:将被调用。

于 2013-06-04T04:46:25.187 回答
0

只要你能通过编译器,无论你作为参数传递的什么都将在运行时被解释为 - 你可以声明一个函数接受一个NSNumber,但如果你将 a 传递UITableView给它,它class仍然是一个UITableView.

于 2013-06-04T04:01:40.330 回答