ios - 期望参数类型为整数,但获取的是 id

标签 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 作为类型吗?

最佳答案

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

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

这是您使用协议(protocol)的示例:

@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)将返回从协议(protocol)获得的有效签名,因此 forwardInvocation: 将被调用。

关于ios - 期望参数类型为整数,但获取的是 id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16909509/

相关文章:

c# - 添加 UITabBarController 时出错

iOS - 从 iOS 应用程序以加密形式在服务器上存储信用卡/借记卡,然后再次从应用程序解密。我怎样才能最安全地管理它?

IOS-如何将json字符串转换为对象

iphone - 单击 UITableViewCell 中的 UITextField

ios - 如何从 didSelectRowAtIndexPath 调用 viewController 内的方法

ios - 为什么 NSTimer 触发的 Action 不能由 block 指定?

objective-c - 如何编码 NSInitation?

IOS/objective-C : Detect Textfield touch but Exclude tap of underlying scrollview

iphone - 将 Unichar 数组转换为单个 NSString

ios - NSInvocation 返回 nil