Q:

Subclassing method with ellipsis array argument?

I would like to subclass an object that has the ellipsis syntax in the init header. i.e.
-(void) initObjectWith:(NSString*)argument arguments:(NSString*)someArgument,...;

I'm unsure how to pass along the arguments array in this case. I suspect it would be something like:
- (void) initObjectWithCustomInitializer:(NSString*)argument additionalArgument:(NSString*)additionalArgument argument:(NSString*) someArgument,... {
  self = [super initObjectWith:argument arguments:someArgument,...];
  if (self) {
     //custom init code here
  }
  return self
}

This compiles but the nil-terminated 'arguments' array is only getting the first argument. How do I pass along the objects of a nil-terminated array?

A:

The superclass that declares that variadic initializer should also declare a non-variadic one that takes a va_list (analogous to how printf has vprintf, for example).  Assuming that case, where the superclass has both:
-(void)init:(id)a arguments:(id)b, ...;

and
-(void)init:(id)a arguments:(id)b variadicArgs:(va_list)args;

You would do something like:
- (void)myInit:(id)a newArg:(id)c arguments:(id)b, ...
{
    va_list v;
    va_start(v, b);

    self = [super init:a arguments:b variadicArgs:v];
    if (self) {
        //custom init code here
    }

    va_end(v);
    return self;
}

Of course, you should be sure to have a non-variadic version of your new initializer, too!

A:

Due to the way varargs are actually implemented, and the limitations of C language, it isn't possible to pass ... args down the callchain without a va_list-taking function to call unless you:

Use assembly language appropriate to every platform on which your code may run
Know intimate details of how the compiler implements va_list et al., or
Try to write a function that somehow computes every possible combination of argument types and passes them along manually.

Of these options, (3) is obviously impractical in any realistic case, and (2) is subject to change without notice at any time. That leaves us with (1), assembly language for each platform on which your code runs.
Internally, varargs are implemented in an ABI-specific manner for each architecture. Conceptually, ... says "I'm going to pass all the arguments I want as if I were calling a function that took those arguments, and it's up to you to figure out where to pick up each argument from." Let's take the example of an architecture that passes all its arguments on the stack, such as i386 on OS X and the iOS Simulator.
Given the following function prototype and call:
void f(const char * const format, ...);
/* ... */
f("lUf", 0L, 1ULL, 1.0);

The compiler will generate the following assembly (as written by me; a real compiler will probably produce a somewhat different calling sequence with the same effect):
leal L_str, %eax
pushl %eax
movl $0x3f800000, %eax
pushl %eax
movl $0x00000000, %eax
pushl %eax
movl $0x00000001, %eax
pushl %eax
movl $0x00000000, %eax
pushl %eax
call _f

The effect of this is to push each parameter onto the stack in reverse order. Here's the secret trick: The compiler would have done the same thing if f() had been declared like this:
void f(const char * const format, long arg1, unsigned long long arg2, float arg3);

This means that if your function can copy the parameter area of the stack and call the vararg-taking function, the args will simply pass through. Problem: There's no generic way to figure out how big this parameter area is! On i386, in a function that has a frame pointer that is also called from a function that has a frame pointer, you can cheat and copy rbp - *rbp bytes, but that's inefficient and won't work for all cases (especially functions that take struct parameters or return structs).
Then you have architectures like armv6 and armv7, where most parameters are passed in registers which must be carefully preserved, x86_64, where parameters are passed in registers and a xmm register count is passed in %al, and ppc, where stack locations and registers are both mapped to parameters!
The only bulletproof way to forward arguments without using a va_list is to reimplement the entire architecture ABI logic in your code using assembly for each architecture, the same way the compiler does.
This is also essentially the same problem that objc_msgSend() solves.
"So wait!" you now say. "Why can't I just call objc_msgSend instead of messing around with assembly this way?!"
Answer: Because you have no way to tell the compiler, "don't mangle anything on the stack and don't wipe out any registers you don't see me using". You would still have to write an assembly routine that forwarded the call to the superclass implementation - before doing any work whatsoever in your subclass implementation - and then returned to yours, all while minding the same things objc_msgSend() does, such as the need for _stret and _fpret variants and implementations on at least three architectures (armv7, i386, x86_64 - and depending upon your need for backwards and forwards compatibility, also potentially ppc, ppc64, armv6, and armv7s).
For plain varargs, the compiler is using its intimate knowledge of your calls and the calling conventions of the target(s) to do this work behind the scenes when it creates a va_list. C doesn't give direct access to any of this information. And objc_msgSend() is the Objective-C compiler and runtime redoing it all again so you can write method calls without using va_list all the time. (Also, on some architectures, it's more efficient to be able to pass parameters to a known calling list than to use varargs conventions).
So, unfortunately, you can't do it without putting hugely more work into the effort than it's likely be worth. Class implementors, let this be a lesson to you - whenever you provide a method that takes variadic arguments, also provide a version of the same method that accepts a va_list in lieu of .... NSString is a great example, with initWithFormat: and initWithFormat:arguments:.

