【问题标题】:Performing dynamic class method calls in Objective-C with more than two parameters在 Objective-C 中使用两个以上的参数执行动态类方法调用
【发布时间】:2013-07-29 12:18:22
【问题描述】:

我有一个方法可以动态创建不同类的新对象,并且希望能够在这些类创建时对它们执行选择器。使用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 工作原理的某些内容,或者是否有更聪明的方法来做到这一点?

【问题讨论】:

  • 尽量避免以这种方式调用任何 API。您将面临许多运行时错误,这些错误可以通过编译时间检查轻松避免。仅当您在运行时创建不能静态声明的类时才需要这样做。在您知道类的实例上调用方法只需要强制转换。这可能会导致一些冗余代码,但编译器将有更好的机会告诉你你搞砸了。
  • 问题是这些是类方法,类是未知的。如果它们是实例方法,则可以通过协议和一些强制转换轻松解决,但我不知道如何通过类来解决。
  • 代码提示我这是一些归档功能。你能重写解决方案以符合 NSCoding 吗?
  • 确实如此。我决定以不同的方式重写它,为每个类创建单独的方法。由于代码是根据协议定义生成的,因此工作量并不大。不过感谢您的提示:)

标签: ios objective-c cocoa


【解决方案1】:

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

【讨论】:

  • 谢谢,这正是我需要的提示。虽然我决定放弃 NSInvocation 解决方案。
【解决方案2】:

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];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-25
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    相关资源
    最近更新 更多