2011-01-26 14 views
53

quizás esto sea obviamente simple para la mayoría de ustedes, pero podrían dar un ejemplo de cómo crear métodos similares (en objetivo-C) y funciones en C para crear funciones como NSString 's stringWithFormat: o NSLog()Cómo crear métodos de argumentos variables en Objective-C

Sólo para recordar:

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

me gustaría crear la NSString similar al' método s stringWithFormat:, NSURL - urlWithFormat.

Gracias de antemano.

Respuesta

115

Lo que estos se denominan, en general, es "funciones variadic" (o métodos, por así decirlo) .

para crear esta, simplemente final su Declartion método con , ..., como en

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

En este punto, es probable que desee para envolverlo en una función printf -como, como la aplicación de uno de los de cero está intentando, en el mejor de los casos.

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

Nota el uso de NSLogv y no NSLog; considere NSLog(NSString *, ...); contra NSLogv(NSString *, va_list);, o si quiere una cadena; initWithFormat:arguments: en NSString *.


Si, por el contrario, usted no está trabajando con cadenas, sino más bien algo como

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

las cosas se ponen mucho más fácil.

En ese caso, en lugar de una función al estilo vprintf, utilice un bucle pasando por args, asumiendo Identificación medida que avanza, y analizarlos como lo haría en cualquier bucle.

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

Esta última muestra, por supuesto, asume que la lista va_args no tiene ningún límite.

Nota: Con el fin de hacer este trabajo que podría que incluir <stdarg.h>; pero si la memoria sirve, esto se incluye en conexión con NSLogv, lo que significa que se reduce a través de "Foundation.h", por lo tanto también "AppKit.h" y "Cocoa.h", así como una cantidad de otros; así que esto debería funcionar de la caja.

+4

Una cosa para mencionar aquí es que, el primer parámetro de NSString aquí viene como formato, y el otro se pasa en el argumento variable. ¿derecho? Entonces, antes de ingresar al bucle for, tiene que manejar un parámetro. – karim

+0

Sin embargo, ¿es posible evitar la terminación 'nil'? p.ej. obtener la longitud de los argumentos variables? – karim

+0

@karim: No es posible con C varargs saber el número y los tipos de los argumentos. La función llamada tiene que saber de alguna manera los tipos y cuándo detenerse. – 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); 
} 

Si desea pasar los argumentos variables a stringWithFormat :, usar algo como:

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

Versión ARC: NSString * s = [[NSString alloc] initWithFormat: argumentos de formato: args]; – godzilla

8

Una cosa para mencionar aquí es que, el primer parámetro de NSString aquí viene como formato, y el otro se pasa en el argumento variable. ¿derecho? Entonces, antes de ingresar al bucle for, tiene que manejar un parámetro.

- (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, @""); 
} 
Cuestiones relacionadas