Ios 使用两个以上的参数在Objective-C中执行动态类方法调用

Ios 使用两个以上的参数在Objective-C中执行动态类方法调用,ios,objective-c,cocoa,Ios,Objective C,Cocoa,我有一个方法,可以动态创建不同类的新对象,并希望能够在创建这些类时对它们执行选择器。使用performSelector:withObject:本可以工作,但方法有四个参数。我使用NSInvocation尝试了以下代码,但由于它是无法识别的选择器而出错 NSInvocation *call = [NSInvocation invocationWithMethodSignature:[NSClassFromString(className) methodSignatureForSelector:@s

我有一个方法,可以动态创建不同类的新对象,并希望能够在创建这些类时对它们执行选择器。使用
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,并将
@选择器设置为如下所示:

NSInvocation *call = [[NSInvocation alloc] init];
call.selector = @selector(nameofselector);
然而,这会导致
call
为零,所以我想这是不允许的


关于NSInvocation如何工作,我是否遗漏了一些东西,或者是否有更聪明的方法来实现这一点?

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

苹果文档只告诉我们第一个参数(带有标记0)代表目标对象(即“自我”)。正如文档所解释的,第一个参数是使用setTarget:方法设置的

因此,您需要从2开始使用NSInvocation的索引


请参见此处:尽量避免以这种方式调用任何API。您将面临许多运行时错误,这些错误可以通过编译时检查轻松避免。只有在运行时创建了不能静态声明的类时,才需要这样做。在已知类的实例上调用方法只需要强制转换。这可能会导致一些冗余代码,但编译器会有更好的机会告诉你,你搞砸了。问题是,这些是类方法,而类是未知的。如果它们是实例方法,那么可以通过协议和一些强制转换轻松解决,但我不知道如何通过类解决这个问题。代码告诉我这是一些archiver功能。您能否重写解决方案以符合NSCoding?确实如此。我决定以不同的方式重写它,为每个类创建单独的方法。因为代码是从协议定义生成的,所以工作并不多。谢谢你的提示:)谢谢,那正是我需要的提示。尽管我决定离开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];