+3  A: 

You've almost got it; just a couple of tweaks:

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

That should do what you're looking for.

Dave DeLong
+3  A: 

I think what you want is something like:

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

The stdarg.h va_* macros are used when a function (or, in this case, method) takes a variable number of arguments, as specified by "...". va_start() is used to find the start of where the variable number of arguments begins. As such, it needs to know a functions/methods last argument (the one just before the "...") in order to determine where the variable number of arguments starts. This is a somewhat simplified explanation since what actually happens under the hood is very ABI/Compiler specific. The most important point is that the second argument to va_start() is always the name of the variable 'just before the "..."'.

va_end() should be "called" (it's really a macro, not a function) for maximum portability. Again, this whole variable arguments thing is deep, deep black magic. Depending on the specifics of the compiler and ABI, va_end() may not do anything at all. On the other hand, failure to use va_end() may cause your program to crash when the return statement is reached because the stack frame (if there even is one) is no longer properly set up to actually perform a return.

johne
Woops, I misunderstood how va_start() works. I guess http://numbergrinder.com/node/35 doesn't explain it clearly enough. I thought the second parameter to va_start() was the actual count of how many params were sent to the function; and that it had an 'overload' which took in a format string that determined the count based on how many unescaped %'s there were in the format string... Wow that makes it so much easier that you don't have to determine the count yourself. Thanks for the explanation.
Senseful