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

Sen*_*ful 7 objective-c nsstring

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

+ (NSString *) myFormattedString:(NSString *)format, ...;
Run Code Online (Sandbox Code Playgroud)

我希望它在我的选择之前添加一个字符串(例如@"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];
}
Run Code Online (Sandbox Code Playgroud)

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

joh*_*hne 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];
}
Run Code Online (Sandbox Code Playgroud)

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

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


Dav*_*ong 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];
}
Run Code Online (Sandbox Code Playgroud)

那应该做你想要的.