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

时间:2022-06-10 20:08:29

maybe this will be obviously simple for most of you, but could you please give an example how to create similar methods (in objective-C) and functions in C to create functions like NSString's stringWithFormat:, or NSLog()

也许这对大多数人来说显然很简单,但是请给出一个示例,如何创建类似的方法(在objective-C中)和C中的函数来创建像NSString的stringWithFormat:或NSLog()这样的函数

Just to remind:

提醒一下:

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

I'd like to create the similar to NSString's method stringWithFormat:, NSURL - urlWithFormat.

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

Thank you in advance.

提前谢谢你。

3 个解决方案

#1


116  

What these are called, generally, is "variadic functions" (or methods, as it were).

这些通常被称为“可变函数”(或者说是方法)。

To create this, simply end your method declartion with , ..., as in

要创建这个,只需以…结束方法声明。,如

- (void)logMessage:(NSString *)message, ...;

At this point you probably want to wrap it in a printf-like function, as implementing one of those from scratch is trying, at best.

在这一点上,您可能想要将它封装到一个printf函数中,因为从头开始实现其中的一个功能是最好的。

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

Note the use of NSLogv and not NSLog; consider NSLog(NSString *, ...); vs NSLogv(NSString *, va_list);, or if you want a string; initWithFormat:arguments: on NSString *.

注意使用NSLogv,而不是NSLog;考虑NSLog(NSString *,…);vs NSLogv(NSString *, va_list);initWithFormat:参数:NSString *。


If, on the other hand, you are not working with strings, but rather something like

另一方面,如果你不是在处理字符串,而是类似的东西

+ (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;

things get a lot easier.

事情变得简单多了。

In that case, instead of a vprintf-style function, use a loop going through args, assuming id as you go, and parse them as you would in any loop.

在这种情况下,不是使用vprintf样式的函数,而是使用一个遍历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);
}

This last sample, of course, assumes that the va_args list is nil-terminated.

当然,最后一个示例假设va_args列表是nil终止的。

Note: In order to make this work you might have to include <stdarg.h>; but if memory serves, this gets included in connection with NSLogv, meaning it comes down by way of "Foundation.h", therefore also "AppKit.h" and "Cocoa.h", as well as a number of others; so this should work out of the box.

注意:为了完成这项工作,您可能需要包含 ;但是如果记忆起作用,这就被包含在NSLogv中,意思是它通过“基础”来实现。AppKit h”,因此也”。h”和“可可。h",以及其他一些;所以这个应该是开箱即用的。

#2


19  

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

If you want to pass the variable arguments to stringWithFormat:, use something like:

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

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

#3


8  

One thing to mention here is that, the first NSString parameter here comes as format, and the other are passed in the variable argument. right? So before entering the for loop, you have one parameter to handle.

这里需要注意的一点是,这里的第一个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, @"");
}

#1


116  

What these are called, generally, is "variadic functions" (or methods, as it were).

这些通常被称为“可变函数”(或者说是方法)。

To create this, simply end your method declartion with , ..., as in

要创建这个,只需以…结束方法声明。,如

- (void)logMessage:(NSString *)message, ...;

At this point you probably want to wrap it in a printf-like function, as implementing one of those from scratch is trying, at best.

在这一点上,您可能想要将它封装到一个printf函数中,因为从头开始实现其中的一个功能是最好的。

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

Note the use of NSLogv and not NSLog; consider NSLog(NSString *, ...); vs NSLogv(NSString *, va_list);, or if you want a string; initWithFormat:arguments: on NSString *.

注意使用NSLogv,而不是NSLog;考虑NSLog(NSString *,…);vs NSLogv(NSString *, va_list);initWithFormat:参数:NSString *。


If, on the other hand, you are not working with strings, but rather something like

另一方面,如果你不是在处理字符串,而是类似的东西

+ (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION;

things get a lot easier.

事情变得简单多了。

In that case, instead of a vprintf-style function, use a loop going through args, assuming id as you go, and parse them as you would in any loop.

在这种情况下,不是使用vprintf样式的函数,而是使用一个遍历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);
}

This last sample, of course, assumes that the va_args list is nil-terminated.

当然,最后一个示例假设va_args列表是nil终止的。

Note: In order to make this work you might have to include <stdarg.h>; but if memory serves, this gets included in connection with NSLogv, meaning it comes down by way of "Foundation.h", therefore also "AppKit.h" and "Cocoa.h", as well as a number of others; so this should work out of the box.

注意:为了完成这项工作,您可能需要包含 ;但是如果记忆起作用,这就被包含在NSLogv中,意思是它通过“基础”来实现。AppKit h”,因此也”。h”和“可可。h",以及其他一些;所以这个应该是开箱即用的。

#2


19  

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

If you want to pass the variable arguments to stringWithFormat:, use something like:

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

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

#3


8  

One thing to mention here is that, the first NSString parameter here comes as format, and the other are passed in the variable argument. right? So before entering the for loop, you have one parameter to handle.

这里需要注意的一点是,这里的第一个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, @"");
}