2011-01-26 14 views
53

forse questo sarà ovviamente semplice per la maggior parte di voi, ma potreste per favore dare un esempio su come creare metodi simili (in oggettivo C) e funzioni in C per creare funzioni come NSString 's stringWithFormat:, o NSLog()Come creare metodi di argomenti variabili in Objective-C

solo per ricordare:

[NSString stringWithFormat:@"example tekst %i %@ %.2f",122,@"sth",3.1415"]; 
NSLog(@"account ID %i email %@",accountID,email); 

mi piacerebbe creare il simile a NSString' s metodo stringWithFormat:, NSURL - urlWithFormat.

Grazie in anticipo.

risposta

115

Che questi sono chiamati, in genere, è "funzioni variadic" (o metodi, per così dire) .

per creare questa, semplicemente fine il metodo declartion con , ..., come in

- (void)logMessage:(NSString *)message, ...; 

A questo punto, probabilmente si vuole avvolgerlo in una funzione printf -come, come attuazione di uno di quelli da zero sta cercando, al meglio.

- (void)logMessage:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 
    NSLogv(format, args); 
    va_end(args); 
} 

Nota l'uso di NSLogv e non NSLog; considerare NSLog(NSString *, ...); rispetto a NSLogv(NSString *, va_list); o se si desidera una stringa; initWithFormat:arguments: su NSString *.


Se, d'altra parte, non si è lavorare con le stringhe, ma piuttosto qualcosa come

+ (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; 

le cose si fanno molto più facile.

In tal caso, invece di una funzione di tipo vprintf, utilizzare un ciclo passante per args, assumendo l'ID mentre si va e analizzarli come si farebbe in qualsiasi ciclo.

- (void)logMessage:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 

    id arg = nil; 
    while ((arg = va_arg(args,id))) { 
    /// Do your thing with arg here 
    } 

    va_end(args); 
} 

Questo ultimo esempio, ovviamente, presuppone che la lista va_args sia chiusa da zero.

Nota: Al fine di rendere questo lavoro si potrebbe devono includere <stdarg.h>; ma se la memoria serve, questa viene inclusa in connessione con NSLogv, il che significa che viene giù per mezzo di "Foundation.h", quindi anche "AppKit.h" e "Cocoa.h", così come un numero di altri; quindi questo dovrebbe funzionare fuori dagli schemi.

+4

Una cosa da ricordare qui è che il primo parametro NSString viene qui in formato e l'altro viene passato nell'argomento variabile. destra? Quindi, prima di entrare nel ciclo for, hai un parametro da gestire. – karim

+0

Tuttavia, è possibile evitare la terminazione 'nil'? per esempio. ottenere la lunghezza degli argomenti variabili? – karim

+0

@karim: non è possibile con C varargs conoscere il numero e i tipi degli argomenti. La funzione chiamata deve in qualche modo conoscere i tipi e quando fermarsi. – newacct

19
- (void)methodWithFormat:(NSString*)format, ... { 
    va_list args; 
    va_start(args,format); 
    //loop, get every next arg by calling va_arg(args,<type>) 
    // e.g. NSString *arg=va_arg(args,NSString*) or int arg=(args,int) 
    va_end(args); 
} 

Se si desidera passare gli argomenti variabile a stringWithFormat :, usare qualcosa come:

NSString *s=[[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 
+1

Versione ARC: NSString * s = [[NSString alloc] initWithFormat: format arguments: args]; – godzilla

8

Una cosa da ricordare qui è che il primo parametro NSString viene qui in formato e l'altro viene passato nell'argomento variabile. destra? Quindi, prima di entrare nel ciclo for, hai un parametro da gestire.

- (NSString *) append:(NSString *)list, ... 
{ 
    NSMutableString * res = [NSMutableString string]; 
    [res appendString:list]; 

    va_list args; 
    va_start(args, list); 
    id arg = nil; 

    while((arg = va_arg(args, id))){ 
     [res appendString:arg]; 
    } 
    va_end(args); 
    return res; 
} 

- (void) test_va_arg 
{ 
    NSString * t = [self append:@"a", @"b", @"c", nil]; 
    STAssertEqualObjects(@"abc", t, @""); 
} 
Problemi correlati