Ios 确定NSInvocation getArgument中的(void*)指针是对象还是基元

Ios 确定NSInvocation getArgument中的(void*)指针是对象还是基元,ios,objective-c,nsinvocation,Ios,Objective C,Nsinvocation,与此抗争。希望这是可能的,我听起来不傻 我正在编写一个类中破解forwardInvocation。我想做的是将调用转发到一个选择器或另一个选择器,这取决于它是对象还是基本类型。最终目标是我想“装箱”原语,以便将它们添加到数组/字典中。为简单起见,这里通常使用的两种类型的值是NSStrings和enum 简而言之,给定一个指针,有没有办法判断它是否是一个对象 __unsafe_unretained id argument; [anInvocation getArgument:&argume

与此抗争。希望这是可能的,我听起来不傻

我正在编写一个类中破解forwardInvocation。我想做的是将调用转发到一个选择器或另一个选择器,这取决于它是对象还是基本类型。最终目标是我想“装箱”原语,以便将它们添加到数组/字典中。为简单起见,这里通常使用的两种类型的值是NSStrings和enum

简而言之,给定一个指针,有没有办法判断它是否是一个对象

__unsafe_unretained id argument;
[anInvocation getArgument:&argument atIndex:2];

// EXC_BAD_ACCESS if primitive (i.e. NSInteger value of 2 ($1 = 0x00000002) )
if (![argument isKindOfClass:[NSObject class]]) {
    // Box the value
    ...
}
有我可以运行的测试吗?现在,我的代码正在恶作剧地进行这种恶作剧:

// All my enums have at most 10 elements. I'm so bad at code.
if ((NSInteger)argument < 10) {
    // Box the value
    ...
}
//我所有的枚举最多有10个元素。我对代码很在行。
if((NSInteger)参数<10){
//框中输入值
...
}

提前感谢。

您可以从方法签名中获取类型:

NSMethodSignature *signature = [invocation methodSignature];
const char* argType = [signature getArgumentTypeAtIndex:2];
下面列出了这些类型

在调用
getArgument:atIndex:
之前,还应该确保知道类型:

此方法将存储在索引中的参数复制到缓冲区指向的存储中。缓冲区的大小必须足够大,以容纳参数值


如果实际参数的大小大于
sizeof(id)

C中的指针只是表示地址的值,则这将写入堆栈上的
参数。空指针指向的地址处的对象是显式非类型化的。如果目标是拥有一个可以接受任何类型的方法——对象指针、标量或组合——那就行不通了。除了无法从空指针恢复类型之外,如果您实际上是试图直接传入标量而不是传入其地址,这是不可能的,因为编译器需要知道正确的值类型才能发出正确的代码,而且大多数类型都无法转换为具有任何保真度的指针。无论哪种方式,Objective-C的类型系统都不够强大,无法满足您的需要。

如果该方法被声明为使用
void*
,会有什么帮助?他故意对自己隐瞒事实。我以为他在谈论
-(void)getArgument:(void*)buffer atIndex:(NSInteger)index
@ErikKerber中的
void*
,但问题是,一旦你把某个东西伪装成
void*
,它就完全被伪装了。这就是
void*
的意思:您已经扔掉了这个指针指向的所有知识。您必须以其他方式知道。@ErikKerber动态生成setter/getter是完全可能的。毕竟,
@dynamic
就是这样工作的(例如,在核心数据中)。但这并不是你想要的方式。您应该研究
resolveInstanceMethod:
@ErikKerber:另外,在
forwardInvocation:
中,您有一个
NSInvocation
,其中包含一个方法签名,它来自
methodSignatureForSelector:
,您说它返回一个伪签名。所以更大的问题是,您的
NSInvocation
参数是垃圾,因为它是使用垃圾签名构建的。如果签名包含的参数太少,则会丢失参数;如果签名包含太多参数,它将从堆栈中获取垃圾值;如果签名的类型不正确,它可能会以可怕的方式将参数拆分为其他参数。您不仅不知道
参数
是对象指针还是整数或其他什么,甚至不知道
参数
是否包含整个参数,因为它甚至可能不是参数的正确大小。如果参数的大小很大,例如一个结构,那么当您执行
getArgument:
时,它将从
argument
的位置开始写入内存,并继续写入该参数类型的大小,如果该参数类型的大小大于指针的大小,将覆盖堆栈上的其他内容。
__unsafe_unretained id argument;
[anInvocation getArgument:&argument atIndex:2];