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