包装[NSString stringWithFormat:]的正确方法是什么?

时间:2009-07-30 21:04:19

标签: objective-c nsstring

假设我有一个带签名的方法:

+ (NSString *) myFormattedString:(NSString *)format, ...;

我希望它前置我选择的字符串(例如@“Foo:”)。我想最好的方法是使用[myString initWithFormat:arguments:],但是你如何实现这个方法?


<击> 我尝试了以下操作,但是我收到了评论中指定的警告:

+ (NSString *) myFormattedString:(NSString *)format, ... {
  char *buffer;
  [format getCString:buffer maxLength:[format length] encoding:NSASCIIStringEncoding];

  va_list args;
  va_start(args, buffer); // WARNING: second parameter of 'va_start' not last named argument

  NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
  [str autorelease];

  return [NSString stringWithFormat:@"Foo: %@.", str];
}

我假设va_start()可以接受(char *)的原因是因为我在manual page of STDARG(3)上看到的例子。如果我完全错误的话,请随意完全重写该方法。

2 个答案:

答案 0 :(得分:15)

我认为你想要的是:

+ (NSString *) myFormattedString:(NSString *)format, ... {
  va_list args;
  va_start(args, format);
  NSString *str = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
  va_end(args);
  return [NSString stringWithFormat:@"Foo: %@.", str];
}

当函数(或者,在本例中为方法)采用可变数量的参数时,使用stdarg.h va_ *宏,由“...”指定。 va_start()用于查找可变数量的参数开始的起点。因此,它需要知道函数/方法的最后一个参数(就在“...”之前的那个),以便确定变量数量的参数开始的位置。这是一个稍微简化的解释,因为在引擎盖下实际发生的是非常ABI /编译器特定的。最重要的一点是,va_start()的第二个参数始终是“...”之前的变量名称。

va_end()应该被“调用”(它实际上是一个宏,而不是一个函数),以实现最大的可移植性。同样,这整个变量论证的事情是深刻的,深黑魔法。根据编译器和ABI的具体情况,va_end()可能根本不做任何事情。另一方面,未能使用va_end()可能会导致程序在达到return语句时崩溃,因为堆栈帧(如果有的话)不再正确设置为实际执行返回。

答案 1 :(得分:8)

你几乎得到了它;只是几个调整:

+ (NSString *) myFormattedString:(NSString *)format, ... {
  va_list args;
  va_start(args, format);

  NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
  [str autorelease];

  va_end(args);

  return [NSString stringWithFormat:@"Foo: %@.", str];
}

那应该做你想要的。