【问题标题】:How to pass an array to an objc method that expects var args (eg ...')如何将数组传递给需要 var args 的 objc 方法(例如 ...')
【发布时间】:2013-07-17 01:28:55
【问题描述】:

我在一个库中有一个方法,看起来像这样:

- (id)initWithSomeObjects:(NSString *)something, ... NS_REQUIRES_NIL_TERMINATION;

我真的很想用数组而不是 var args 来调用它,因为我想传入的对象数量是可变的。

有没有什么方法,使用 performSelector 或 NSInvocation 或 objc_msgSend 或其他什么,我可以调用 var args 方法,参数来自数组?

【问题讨论】:

  • 我在这里找到了一个方法,但是在xcode4+下编译不出来-cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html
  • 什么是编译错误?
  • 那个程序不会做你想做的事。这是将NSArray 的内容传输到va_list。您的方法不需要va_list,它需要可变数量的参数。 va_list 本身就是一个类型——只是一个字节缓冲区,但它是一个参数。您的方法看起来像 -(id)initWithSomeObjects:(va_list)objs 比较 -[NSString initWithFormat:]-[NSString initWithFormat:arguments:]

标签: objective-c performselector nsinvocation objc-message-send


【解决方案1】:

没有简单的方法可以做到这一点,因为参数的传递方式涉及到特定系统调用 ABI 的丑陋细节,你必须知道例如有多少参数被放入寄存器,剩余的参数如何处理等等。这会涉及到汇编,不能用一般的方式来完成。

一般来说,任何具有像这样的可变参数的方法或函数的 API 也可以

  1. 提供另一种采用va_list 参数的方法(例如-[NSString initWithFormat:] 具有-[NSString initWithFormat:arguments:])。如果是这种情况,那么您可以使用该技术从您在 cmets 中链接到的文章中构造 va_list。 (即使构造 va_list 也是系统特定的且不可移植的。但至少它可以在 Mac 和 iPhone 上运行,而且操作相当简单且不涉及组装。)
  2. 提供另一种方法,该方法采用 NSArray * 或 C 元素数组(例如,-[NSArray initWithObjects:] 具有 -[NSArray initWithObjects:count:]
  3. 有方法一个一个地添加元素,这样整体效果就和把它们一起传给varargs方法一样(例如-[UIAlertView initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:]末尾的varargs按钮标题可以通过调用-[UIAlertView addButtonWithTitle:]multiple来实现次)。

如果您的 varargs API 没有上述任何一种,那么它就是一个设计糟糕的 API,您应该向编写它的人投诉。如果你真的遇到这种情况,我猜可以使用 libffi 之类的东西,它可以让你动态地进行函数调用,并处理依赖于系统的调用机制的本质。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2020-08-27
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    相关资源
    最近更新 更多