Как передать переменное количество аргументов в метод2 из метода1, который принимает переменное количество аргументов?

Предположим, что у нас есть методы:

-(instancetype) initWithElements:(id)firstElement, ... NS_REQUIRES_NIL_TERMINATION;
+(instancetype) objWithElements:(id)firstElement, ... NS_REQUIRES_NIL_TERMINATION;

Я понимаю, как работать с переменным числом аргументов в -initWithElements:, но я не понимаю, как передавать переменные от -objWithElements: до -initWithElements:.

Я имею в виду, я хочу написать что-то вроде:

+(instancetype) objWithElements:(id)firstElement, ... NS_REQUIRES_NIL_TERMINATION {
    return [[[self] initWithElements:ELEMENTS] autorelease];
}

Возможно ли это?

Единственное решение для моей проблемы, которое я вижу, это хранить аргументы в массиве и использовать вспомогательный метод, который будет инициировать объект с заданным массивом.

Ответ 1

Нет, в C (и Objective-C) невозможно передать вариационные аргументы.

Идиоматическое решение состоит в том, чтобы получить инициализатор, который принимает va_list, сделать , который как назначенный инициализатор, а затем вызвать его из любого другого метода. Из-за вариационного метода это выглядело бы так:

- (instancetype)initWithVarargs:(id)first, ...
{
    va_list args;
    va_start(args, first);
    id obj = [self initWithFirst:first VAList:args];
    va_end(args);
    return obj;
}

и здесь назначенный инициализатор, который принимает аргумент va_list:

- (id)initWithFirst:(id)first VAList:(va_list)args
{
    id obj;
    while ((obj = va_arg(args, id)) != nil) {
        // do actual stuff
    }
    // the return self, etc.
}

J

Ответ 2

Я бы создал две версии каждого метода; который принимает переменные аргументы (...) и другой (где фактическая реализация) с помощью va_list:

-(instancetype) initWithElements:(id)firstElement, ... NS_REQUIRES_NIL_TERMINATION;
-(instancetype) initWithElementsImpl:(va_list)va;
+(instancetype) objWithElements:(id)firstElement, ... NS_REQUIRES_NIL_TERMINATION;
+(instancetype) objWithElementsImpl:(va_list)va;

Это позволит версии va_list просто передать этот параметр другому методу va_list без каких-либо работ.

В версии var args (...) будет использоваться va_start() et al., чтобы создать объект va_list для перехода к версии метода va_list.