期望参数类型为整数但是获取id

时间:2013-06-04 03:50:17

标签: ios objective-c nsinvocation

我正在使用objective-c的forwardInvocation:功能,我需要知道方法收到的类型。在我的示例中,我传递的是int,但getArgumentTypeAtIndex:告诉我这是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作为类型?

2 个答案:

答案 0 :(得分: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:的默认实现(来自NSObject)将返回从协议获得的有效签名,因此将调用forwardInvocation:

答案 1 :(得分:0)

只要你能通过编译器,无论你作为参数传递的是什么,都会在运行时被解释为 - 你可以声明一个函数需要NSNumber,但是你传递了{{1对它来说,它的UITableView仍然是class