代码之家  ›  专栏  ›  技术社区  ›  Alex Wayne

目标-C传递…无终止的论点列表

  •  20
  • Alex Wayne  · 技术社区  · 15 年前

    有一些问题 ... 在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];
    }
    

    如何简单地从传入的参数虹吸到传出的参数,保持完全相同 终止列表?

    3 回复  |  直到 11 年前
        1
  •  40
  •   Dave DeLong    15 年前

    你不能这样做,至少你不想这样做。要执行的操作(传递变量参数)需要启用初始值设定项 UIAlertView 接受一个 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];
    }
    

    当然,这是非常具体的问题。真正的答案是“不能将变量参数列表隐式传递给没有 VAI表 参数“。因此,您必须找到解决问题的方法。在您给出的示例中,您希望使用传入的标题创建一个AlertView。幸运的是, uiAlctVIEW 类有一个方法,您可以迭代调用该方法来添加按钮,从而实现相同的总体效果。如果没有这种方法,你就走运了。

    另一个真正混乱的选择是将其变址宏。变量宏如下所示:

    #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]; \
    }
    

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

        2
  •  0
  •   Don    15 年前

    构造一个 NSInvocation 对象?因为参数必须通过指针传递,所以可以将指针传递到以nil结尾的列表。

    您还可以使用 marg_list() 自己构建一个以零结尾的列表。

    这些只是简单的建议,我还没试过。

        3
  •  0
  •   Robin Macharg    11 年前

    这是特定于OP的 UIAlertView -包装箱,仅在iOS7上测试:似乎 uiAlctVIEW 已用初始化 otherButtons:nil ,然后将其样式设置为 UIAlertViewStylePlainTextInput 它不称其代表的 alertViewShouldEnableFirstOtherButton: 验证输入。我不确定这是一个错误还是有意的行为,但它打破了我最不吃惊的原则。这可以通过以下内容进行复制(我假设学员的 “警报视图”应为“第一个其他”按钮: 已实施):

    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Title" 
                                                 message:@"message" 
                                                delegate:self         
                                       cancelButtonTitle:@"Cancel" 
                                       otherButtonTitles:nil];
    [av setAlertViewStyle:UIAlertViewStylePlainTextInput];
    [av addButtonWithTitle:@"OK"];
    [av show];
    

    解决方案,因为uialertview高兴地接受 其他按钮:无 ,是初始化 uiAlctVIEW 使用OtherButtonTitles(可以为零),并迭代变量参数,如上所述:

    + (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];
    
        // add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here
    
        if (otherButtonTitles != nil) {
            va_list args;
            va_start(args, otherButtonTitles);
            NSString * title = nil;
            while(title = va_arg(args,NSString*)) {
                [alert addButtonWithTitle:title];
            }
            va_end(args);
        }
    
        [alert show];
    }