Ios 参数类型应为整数,但应改为获取id
我正在使用objective-c的Ios 参数类型应为整数,但应改为获取id,ios,objective-c,nsinvocation,Ios,Objective C,Nsinvocation,我正在使用objective-c的forwardInvocation:特性,我需要知道该方法收到的参数的类型。在我的示例中,我给它传递了一个int,但是getArgumentTypeAtIndex:告诉我它是一个id。下面是一个简单的例子: @interface Do : NSObject + (void) stuff:(int)x; @end @implementation Do + (NSMethodSignature *) methodSignatureForSelector:(SEL)s
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
作为类型吗?只要你能通过编译器,无论你作为参数传递什么,在运行时都会被解释为这样-你可以声明一个函数接受一个NSNumber
,但如果你把UITableView
传递给它,它的类
仍然是一个UITableView
只要你能通过编译器,无论你作为参数传递什么,在运行时都会被解释为这样-你可以声明一个函数接受一个NSNumber
,但是如果你把UITableView
传递给它,这是类
仍将是UITableView
问题是您实际上没有东西:
方法在类上,因此方法签名选择器:
将返回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
@protocol协议
@可选的
+(空)材料:(int)x;
@结束
@接口Do:NSObject
@结束
@实现
+(void)转发调用:(NSInvocation*)i
{
const char*argType=[i.methodSignature getArgumentTypeAtIndex:2];
NSLog(@“%s==%s”,argType,@encode(id));/@==@
NSLog(@“%s==%s”,argType,@encode(int));/@==i
}
@结束
@可选的
避免对未实现的方法发出任何编译器警告。methodSignatureForSelector:
(来自NSObject
)的默认实现将返回从协议获得的有效签名,因此,forwardInvocation:
将被调用。问题是,类上实际上没有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
@protocol协议
@可选的
+(空)材料:(int)x;
@结束
@接口Do:NSObject
@结束
@实现
+(void)转发调用:(NSInvocation*)i
{
const char*argType=[i.methodSignature getArgumentTypeAtIndex:2];
NSLog(@“%s==%s”,argType,@encode(id));/@==@
NSLog(@“%s==%s”,argType,@encode(int));/@==i
}
@结束
@可选的
避免对未实现的方法发出任何编译器警告。methodSignatureForSelector:
(来自NSObject
)的默认实现将返回从协议获得的有效签名,因此将调用forwardInvocation:
。这是可行的,但在我的情况下,我需要将协议添加一个类别,不在原始的@接口
声明上。无论出于何种原因,这似乎不起作用。我最终直接从协议中提取签名:[NSMethodSignatureWithObjectTypes:protocol_getMethodDescription(@protocol(…),selector,0,0)。types]
这是可行的,但在我的情况下,我需要将协议添加一个类别,不在原始的@接口
声明上。不管出于什么原因,这似乎不起作用。我最终直接从协议中提取签名:[NSMethodSignatureWithObjectTypes:protocol_getMethodDescription(@protocol(…),selector,0,0).types]