如何将数组传递给期望var args的objc方法(例如......')

时间:2013-07-17 01:28:56

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

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

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

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

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

1 个答案:

答案 0 :(得分:5)

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

通常,任何具有类似varargs的方法或函数的API也将

  1. 提供另一种采用va_list参数的方法(例如-[NSString initWithFormat:]-[NSString initWithFormat:arguments:])。如果是这种情况,那么您可以使用该技术从评论中链接到的文章构建va_list。 (即使构建va_list也是系统特定且不可移植的。但至少它可以在Mac和iPhone上运行,并且它非常简单,并且不涉及组装。)
  2. 提供另一种方法,该方法采用NSArray *或C数组元素(例如-[NSArray initWithObjects:]具有-[NSArray initWithObjects:count:]
  3. 有方法逐个添加元素,使整体效果与将它们全部传递到varargs方法相同(例如-[UIAlertView initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:]末尾的varargs按钮标题可以通过调用{{}来实现1}}多次)。
  4. 如果您的varargs API没有上述之一,那么它是一个设计糟糕的API,您应该向编写它的人抱怨。如果你真的碰到这种情况,我猜测可以使用类似libffi的东西,它允许你动态地进行函数调用,并处理系统相关调用机制的细节。