2014-01-09 1 views
10

Angenommen, wir haben Methoden:Wie kann ich eine variable Anzahl von Argumenten an Methode2 von Methode1 übergeben, die eine variable Anzahl von Argumenten akzeptiert?

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

Ich verstehe, wie mit variabler Anzahl von Argumenten in -initWithElements: arbeiten, aber ich verstehe nicht, wie Variablen -objWithElements:--initWithElements: passieren.

Ich meine, ich will wie etwas schreiben:

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

Ist es überhaupt möglich?

Die einzige Lösung für mein Problem sehe ich darin, Argumente in Array zu speichern und Helper-Methode zu verwenden, die Objekt mit gegebenem Array initiieren wird.

Antwort

8

Nein, in C (und Objective-C) können variadische Argumente nicht übergeben werden.

Die idiomatische Lösung ist, sich einen Initialisierer zu erhalten, die eine va_list nimmt, machen dass als designierter initializer und dann von jeder anderen Methode aufrufen. Aus einem variadische Methode, würde dies wie folgt aussehen:

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

und hier ist ein ausgewiesener initializer, die ein va_list Argument:

- (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

+0

Ich sehe. Aber ist das wirklich nötig? - (id) initWithFirst: (id) zuerst VAList: (va_list) args' statt '- (instantype) initWithElementsImpl: (va_list) args'? Ich meine, was ist, wenn der Benutzer etwas wie "[obj initWithVarargs: nil]" eingibt? – d12frosted

+1

@RottenBrain Ich sehe dein Problem nicht. Der Benutzer ruft nur Methoden auf, die existieren. Wenn Sie 'initWithVarargs:' nicht deklarieren, erhält der Benutzer eine Compiler-Warnung/einen Fehler, wenn er versucht, ihn aufzurufen. Allerdings möchten Sie unbedingt ** auch das allererste Objekt an die Methode übergeben (Sie können keine Methoden und Funktionen nur mit variadischen Argumenten schreiben, ein fixes Argument ist immer notwendig). –

6

Ich würde erstellen zwei Versionen jedes Verfahren; eine, die variable Argumente (...) und ein anderer nimmt (wobei die tatsächliche Umsetzung ist) va_list mit:

-(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; 

Dies wird die va_list Version erlauben einfach überhaupt ohne Arbeit, dass der Parameter auf die andere va_list Methode zu übergeben.

Die var args Version (...) wird verwenden va_start() et al das va_listObjekt zu erstellen, um die va_list Version des Verfahrens zu übergeben.