4

我有一个动态创建不同类的新对象的方法,并且希望能够在创建这些类时对它们执行选择器。使用performSelector: withObject:会有效,但这些方法有四个参数。我使用 NSInvocation 尝试了以下代码,但收到关于它是无法识别的选择器的错误。

NSInvocation *call = [NSInvocation invocationWithMethodSignature:[NSClassFromString(className) methodSignatureForSelector:@selector(packWithName:value:writer:forClass:)]];
[call setArgument:&arg1 atIndex:0];
[call setArgument:&arg2 atIndex:1];
[call setArgument:&arg3 atIndex:2];
[call setArgument:&arg4 atIndex:3];
call.target = NSClassFromString(className);
[call invoke];

它还产生以下日志语句:

*** NSForwarding: warning: selector (0x8ed78d0) for message '[garbled random characters]'
does not match selector known to Objective C runtime (0x8b0cd30)-- abort

我还尝试使用 alloc/init 创建 NSInvocation 并设置@selector如下:

NSInvocation *call = [[NSInvocation alloc] init];
call.selector = @selector(nameofselector);

然而,这导致call为零,所以我想这是不允许的。

我是否遗漏了有关 NSInvocation 工作原理的信息,或者是否有更聪明的方法来做到这一点?

4

2 回答 2

6

索引 0 和 1 处的参数不是方法调用的前两个显式参数,而是隐式self_cmd参数。请改用索引 2、3、4 和 5。

于 2013-07-29T12:20:41.360 回答
4

Apple 文档只是告诉第一个参数(索引为 0)代表目标对象(因此是“自我”)。正如文档解释的那样,第一个参数是使用 setTarget: 方法设置的。

所以你需要从 2 开始使用 NSInvocation 的索引。(这意味着你的代码应该是这样的)

NSInvocation *call = [NSInvocation invocationWithMethodSignature:[NSClassFromString(className) methodSignatureForSelector:@selector(packWithName:value:writer:forClass:)]];
[call setArgument:&arg1 atIndex:2];
[call setArgument:&arg2 atIndex:3];
[call setArgument:&arg3 atIndex:4];
[call setArgument:&arg4 atIndex:5];
call.target = NSClassFromString(className);
[call invoke];
于 2013-07-29T13:18:07.340 回答