如何在Objective-C中创建变量参数方法

Chr*_*ski 59 format null xcode objective-c variadic-functions

也许这对你们大多数人来说显然都很简单,但是请你举个例子来说明如何创建类似的方法(在Objective-C中)和C中的函数来创建像NSStrings stringWithFormat:或者类似的函数NSLog().

提醒一下:

[NSString stringWithFormat:@"example tekst %i %@ %.2f", 122, @"sth", 3.1415"];
NSLog(@"account ID %i email %@", accountID, email);
Run Code Online (Sandbox Code Playgroud)

我想创建类似NSString的方法stringWithFormat:,NSURL - urlWithFormat.

Wil*_*and 121

通常,这些被称为"可变函数"(或其方法).

要创建它,只需使用,结束您的方法声明, ...

- (void)logMessage:(NSString *)message, ...;
Run Code Online (Sandbox Code Playgroud)

此时你可能想把它包装在一个类似printf的函数中,因为从头开始实现其中一个就是尝试.

- (void)logMessage:(NSString *)format, ... {
  va_list args;
  va_start(args, format);
  NSLogv(format, args);
  va_end(args);
}
Run Code Online (Sandbox Code Playgroud)

注意使用NSLogv和不NSLog; 考虑NSLog(NSString *, ...);vs NSLogv(NSString *, va_list);,或者你想要一个字符串; initWithFormat:arguments:NSString *.


另一方面,如果你不使用字符串,而是使用类似字符串

+ (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;
Run Code Online (Sandbox Code Playgroud)

事情变得容易多了.

在这种情况下,vprintf使用循环,而不是a- style函数,使用循环args假设id,并像在任何循环中一样解析它们.

- (void)logMessage:(NSString *)format, ... {
  va_list args;
  va_start(args, format);

  id arg = nil;
  while ((arg = va_arg(args,id))) {
  /// Do your thing with arg here
  }

  va_end(args);
}
Run Code Online (Sandbox Code Playgroud)

当然,最后一个示例假定va_args列表以nil结尾.

注意:为了完成这项工作,您可能必须包括<stdarg.h>; 但是如果内存服务,它会被包含在与NSLogv的连接中,这意味着它通过"Foundation.h",因此也是"AppKit.h"和"Cocoa.h",以及其他许多内容; 所以这应该是开箱即用的.

  • 这里要提到的一件事是,第一个NSString参数在这里作为格式,另一个在变量参数中传递.对?因此,在进入for循环之前,您需要处理一个参数. (4认同)

M-f*_*ied 20

- (void)methodWithFormat:(NSString*)format, ... {
  va_list args;
  va_start(args,format);
  //loop, get every next arg by calling va_arg(args,<type>)
  // e.g. NSString *arg=va_arg(args,NSString*) or int arg=(args,int)
  va_end(args);
}
Run Code Online (Sandbox Code Playgroud)

如果要将变量参数传递给stringWithFormat:,请使用以下内容:

NSString *s=[[[NSString alloc] initWithFormat:format arguments:args] autorelease];
Run Code Online (Sandbox Code Playgroud)

  • ARC 版本:NSString *s=[[NSString alloc] initWithFormat:format arguments:args]; (2认同)

kar*_*rim 8

这里要提到的一件事是,第一个NSString参数在这里作为格式,另一个在变量参数中传递.对?因此,在进入for循环之前,您需要处理一个参数.

- (NSString *) append:(NSString *)list, ...
{
    NSMutableString * res = [NSMutableString string];
    [res appendString:list];

    va_list args;
    va_start(args, list);
    id arg = nil;

    while(( arg = va_arg(args, id))){
        [res appendString:arg];
    }
    va_end(args);
    return res;
}

- (void) test_va_arg
{
    NSString * t = [self append:@"a", @"b", @"c", nil];
    STAssertEqualObjects(@"abc", t, @"");
}
Run Code Online (Sandbox Code Playgroud)