有没有一种方法来指定参数位置/索引在NSString stringWithFormat?

C#的语法允许你在一个string格式说明符中指定参数索引,例如:

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

您可以多次使用参数,也可以省略从使用中提供的参数。 另一个问题以%[index]$[format]的forms提到了与C / C ++相同的格式,例如%1$i 。 我一直没有能够得到NSString 完全尊重这个语法,因为从格式中省略参数时它确实performance得很好。 以下内容不能按预期工作(EXC_BAD_ACCESS,因为它试图将age参数取消引用为NSObject *):

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

只有当格式中没有缺less参数时(这似乎是一个奇怪的要求),位置参数才受到尊重:

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

所有这些调用在OS X中正常工作:

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

有没有在Objective-C / Cocoa中使用NSString来完成此操作的方法? 这对本地化的目的是有用的。

NSString和CFString支持reorderable /位置参数。

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

另请参阅Apple的文档:string资源

以下代码修复了此问题中指定的错误。 这是一个解决方法,重新填充占位符来填补空白。

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

经过更多的研究,看来Cocoa在printf尊重位置语法。 因此,另一种模式是:

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

但是,如果在NSString上有这个实现,那将会很好。