Как создать переменные аргументы в Objective-C - PullRequest
57 голосов
/ 26 января 2011

Возможно, это будет очевидно просто для большинства из вас, но не могли бы вы привести пример, как создавать похожие методы (в Objective-C) и функции в C для создания функций, таких как NSString s stringWithFormat:, илиNSLog().

Напоминаю:

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

Я бы хотел создать метод, подобный NSString stringWithFormat:, NSURL - urlWithFormat.

Ответы [ 3 ]

119 голосов
/ 26 января 2011

То, что они называются, как правило, это "функции с переменными числами" (или как бы методы).

Чтобы создать это, просто end ваше объявление метода с , ...,как в

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

В этот момент вы, вероятно, захотите обернуть ее в printf -подобную функцию, поскольку реализация одной из этих функций с нуля в лучшем случае пытается.

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

Обратите внимание на использование NSLogv, а не NSLog;рассмотрите NSLog(NSString *, ...); против NSLogv(NSString *, va_list);, или если вы хотите строку;initWithFormat:arguments: on NSString *.


Если, с другой стороны, вы работаете не со строками, а с чем-то вроде

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

, все становится намного проще.

В этом случае вместо функции в стиле vprintf используйте цикл, проходящий через args, принимая идентификатор по ходу, и анализируйте их, как в любом цикле.

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

В последнем примере, конечно, предполагается, что список va_args завершен нулем.

Примечание: Для того, чтобы эта работа у вас могла иметьвключить <stdarg.h>;но если память служит, это включается в связку с NSLogv, то есть происходит через «Foundation.h», поэтому также «AppKit.h» и «Cocoa.h», а также ряд других;так что это должно работать из коробки.

20 голосов
/ 26 января 2011
- (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);
}

Если вы хотите передать аргументы переменной в stringWithFormat:, используйте что-то вроде:

NSString *s=[[[NSString alloc] initWithFormat:format arguments:args] autorelease];
8 голосов
/ 25 февраля 2014

Здесь следует упомянуть одну вещь: первый параметр 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, @"");
}
...