Как передать массив методу objc, который ожидает var args (например, ')

У меня есть метод в библиотеке, который выглядит так:

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

Я бы очень хотел вызвать его с помощью массива вместо var args, потому что количество объектов, которые я хотел бы передать, можно изменить.

Есть ли способ, используя performSelector, NSInvocation или objc_msgSend или что-то еще, чтобы я мог вызвать метод var args с аргументами, поступающими из массива?


person Chris    schedule 17.07.2013    source источник
comment
Я нашел способ здесь, но он не компилируется под xcode4 + - cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html   -  person Chris    schedule 17.07.2013
comment
Что такое ошибка компиляции?   -  person Wain    schedule 17.07.2013
comment
Эта процедура не сделает того, что вы хотите. Это передача содержимого NSArray в va_list. Ваш метод не принимает va_list, он принимает переменное количество аргументов. va_list - это сам по себе тип - просто байтовый буфер, но это единственный аргумент. Ваш метод будет выглядеть так: -(id)initWithSomeObjects:(va_list)objs Сравнить -[NSString initWithFormat:] и -[NSString initWithFormat:arguments:].   -  person jscs    schedule 17.07.2013


Ответы (1)


Нет простого способа сделать это, потому что то, как передаются аргументы, входит в уродливые детали вызывающего ABI конкретной системы, и вы должны знать, например, сколько аргументов помещается в регистры, как работать с оставшимися аргументами и т. д. И это будет связано с ассемблированием, и это не может быть выполнено в общем виде.

Как правило, любой 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 (например, заголовки кнопок varargs в конце -[UIAlertView initWithTitle:message:delegate:cancelButtonTitle:otherButtonTitles:] можно получить, вызвав -[UIAlertView addButtonWithTitle:] несколько раз).

Если у вас есть API varargs, у которого нет ни одного из вышеперечисленных, значит, это плохо спроектированный API, и вам следует пожаловаться тому, кто его написал. Если вы действительно столкнетесь с такой ситуацией, я предполагаю, что можно было бы использовать что-то вроде libffi, которое позволяет вам выполнять вызовы функций динамически и обрабатывает мельчайшие детали системно-зависимых механизмов вызова.

person newacct    schedule 17.07.2013