versiones plataforma objective framework español ejemplos compiler objective-c cocoa

objective c - plataforma - ¿Hay alguna manera de especificar la posición/índice del argumento en NSString stringWithFormat?



xcode (3)

Después de investigar más, parece que Cocoa respeta la sintaxis posicional en printf . Por lo tanto, un patrón alternativo sería:

char msg[512] = {0}; NSString * format = @"Age %2$i, Name: %1$s"; // loaded from resource in practice sprintf(msg, [format UTF8String], [name UTF8String], age); NSString * message = [NSString stringWithCString:msg encoding:NSUTF8StringEncoding];

Sin embargo, sería bueno si hubiera una implementación de esto en NSString.

C # tiene una sintaxis que le permite especificar el índice del argumento en un especificador de formato de cadena, por ejemplo:

string message = string.Format("Hello, {0}. You are {1} years old. How does it feel to be {1}?", name, age);

Puede usar argumentos más de una vez y también omitir los argumentos que se proporcionan para su uso. Otra pregunta menciona el mismo formato para C / C ++ en la forma de %[index]$[format] , por ejemplo, %1$i . No he podido lograr que NSString respete completamente esta sintaxis, porque se comporta bien al omitir argumentos del formato. Lo siguiente no funciona como se esperaba (EXC_BAD_ACCESS porque intenta desreferenciar el parámetro de age como un NSObject *):

int age = 23; NSString * name = @"Joe"; NSString * message = [NSString stringWithFormat:@"Age: %2$i", name, age];

Los argumentos posicionales se respetan solo si no faltan argumentos del formato (que parece ser un requisito extraño):

NSString * message = [NSString stringWithFormat:@"Age: %2$i; Name: %1$@", name, age];

Todas estas llamadas funcionan correctamente en OS X:

printf("Age: %2$i", [name UTF8String], age); printf("Age: %2$i %1$s", [name UTF8String], age);

¿Hay alguna manera de lograr esto usando NSString en Objective-C / Cocoa? Sería útil para fines de localización.


El siguiente código corrige el error especificado en este problema. Es una solución y renumera los marcadores de posición para llenar las lagunas.

+ (id)stringWithFormat:(NSString *)format arguments:(NSArray*) arguments { NSMutableArray *filteredArguments = [[NSMutableArray alloc] initWithCapacity:arguments.count]; NSMutableString *correctedFormat = [[NSMutableString alloc ] initWithString:format]; NSString *placeHolderFormat = @"%%%d$"; int actualPlaceholderIndex = 1; for (int i = 1; i <= arguments.count; ++i) { NSString *placeHolder = [[NSString alloc] initWithFormat:placeHolderFormat, i]; if ([format rangeOfString:placeHolder].location != NSNotFound) { [filteredArguments addObject:[arguments objectAtIndex:i - 1]]; if (actualPlaceholderIndex != i) { NSString *replacementPlaceHolder = [[NSString alloc] initWithFormat:placeHolderFormat, actualPlaceholderIndex]; [correctedFormat replaceAllOccurrencesOfString:placeHolder withString:replacementPlaceHolder]; [replacementPlaceHolder release]; } actualPlaceholderIndex++; } [placeHolder release]; } if (filteredArguments.count == 0) { //No numbered arguments found: just copy the original arguments. Mixing of unnumbered and numbered arguments is not supported. [filteredArguments setArray:arguments]; } NSString* result; if (filteredArguments.count == 0) { //Still no arguments: don''t use initWithFormat in this case because it will crash: just return the format string result = [NSString stringWithString:format]; } else { char *argList = (char *)malloc(sizeof(NSString *) * [filteredArguments count]); [filteredArguments getObjects:(id *)argList]; result = [[[NSString alloc] initWithFormat:correctedFormat arguments:argList] autorelease]; free(argList); } [filteredArguments release]; [correctedFormat release]; return result; }


NSString y CFString admiten argumentos reordenables / posicionales.

NSString *string = [NSString stringWithFormat: @"Second arg: %2$@, First arg %1$@", @"<1111>", @"<22222>"]; NSLog(@"String = %@", string);

Además, consulte la documentación en Apple: String Resources