Objective-C传递... nil终止参数列表

Ale*_*yne 20 objective-c variadic

...在ObjectiveC中遇到一些问题.

我基本上包装一个方法,并希望接受一个nil终止列表,并直接将相同的列表传递给我正在包装的方法.

这是我的,但它会导致EXC_BAD_ACCESS崩溃.检查当地的变量,它似乎otherButtonTitles只是一个NSString传入的时间otherButtonTitles:@"Foo", nil]

+ (void)showWithTitle:(NSString *)title
              message:(NSString *)message
             delegate:(id)delegate
    cancelButtonTitle:(NSString *)cancelButtonTitle
    otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
                                                     message:message
                                                    delegate:delegate
                                           cancelButtonTitle:cancelButtonTitle
                                           otherButtonTitles:otherButtonTitles] autorelease];
    [alert show];
}
Run Code Online (Sandbox Code Playgroud)

我如何简单地从参数传出到传出参数,从而保留完全相同的nil终止列表?

Dav*_*ong 40

你不能这样做,至少不是你想要的方式.你想做什么(传递变量参数)需要有一个UIAlertView接受a 的初始化器va_list.没有一个.但是,您可以使用以下addButtonWithTitle:方法:

+ (void)showWithTitle:(NSString *)title
              message:(NSString *)message
             delegate:(id)delegate
    cancelButtonTitle:(NSString *)cancelButtonTitle
    otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
                                                     message:message
                                                    delegate:delegate
                                           cancelButtonTitle:cancelButtonTitle
                                           otherButtonTitles:nil] autorelease];
    if (otherButtonTitles != nil) {
      [alert addButtonWithTitle:otherButtonTitles];
      va_list args;
      va_start(args, otherButtonTitles);
      NSString * title = nil;
      while(title = va_arg(args,NSString*)) {
          [alert addButtonWithTitle:title];
      }
      va_end(args);
    }

    [alert show];
}
Run Code Online (Sandbox Code Playgroud)

当然,这是非常特定于问题的.真正的答案是"你不能隐式地将变量参数列表传递给没有参数的方法/函数va_list".因此,您必须找到解决问题的方法.在您给出的示例中,您希望使用传入的标题创建一个alertView.幸运的是,UIAlertView该类有一个方法可以迭代调用添加按钮,从而实现相同的整体效果.如果它没有这种方法,那你就不走运了.

另一个非常混乱的选择是使它成为一个可变的宏.可变宏看起来像这样:

#define SHOW_ALERT(title,msg,del,cancel,other,...) { \
  UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; \
  [_alert show]; \
}
Run Code Online (Sandbox Code Playgroud)

但是,即使使用可变参数宏方法,每次要执行此操作时仍需要自定义宏.这不是一个非常可靠的选择.

  • 如果你需要接受一个变量参数列表(正如Dave上面的答案非常好)然后构造一个非变量API的调用,请使用NSInvocation. (3认同)