Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 参数类型应为整数,但应改为获取id_Ios_Objective C_Nsinvocation - Fatal编程技术网

Ios 参数类型应为整数,但应改为获取id

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

我正在使用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
作为类型吗?

只要你能通过编译器,无论你作为参数传递什么,在运行时都会被解释为这样-你可以声明一个函数接受一个
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]