如何在[UIAlertView initWithTitle ...]中调用一个采用可变数量参数的方法的超类实现?

时间:2011-03-31 23:35:22

标签: iphone objective-c variables methods arguments

OS X Developer Library展示了如何在以下技术文章中创建一个采用可变数量args的方法:http://developer.apple.com/library/mac/#qa/qa1405/_index.html

我正在试图弄清楚是否可以继承带有变量args并调用超类实现的方法的现有实现。

以UIActionSheet为例,请看下面的代码。调用超类initWithTitle方法只传递第一个'otherButtonTitle'。我不知道如何传递变量参数列表中包含的剩余字符串。

// MyActionSheet.m

- (id)initWithTitle:(NSString *)title
           delegate:(id < UIActionSheetDelegate >)delegate
  cancelButtonTitle:(NSString *)cancelButtonTitle
destructiveButtonTitle:(NSString *)destructiveButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
    // this calls the superclass initWithTitle: method but does not
    // pass NIL terminated list of strings
    self = [super initWithTitle:title
                       delegate:delegate
              cancelButtonTitle:cancelButtonTitle
         destructiveButtonTitle:destructiveButtonTitle
              otherButtonTitles:otherButtonTitles, nil];
    if (self) {
        // custom initialization
    }
    return self;
}

我可以使用va_list,va_start,va_end获取args,但不知道如何将它们传递给超类方法。

如果有人试图告诉我我可以用不同的方式做到这一点(例如,不要传递变量args但是使用va_list,va_start,va_end创建一个字符串数组并调用addButtonWithTitle:多次,我我知道我可以做到这一点。我使用UIActionSheet作为例子。在其他情况下,使用变量args子类化方法的能力将是有用的,我想学习如何做到我所问的是否可能

谢谢!

3 个答案:

答案 0 :(得分:6)

Cocoa中的许多类都有采用可变数量参数的方法。在大多数情况下,这些类也将具有采用va_list的等效方法。如果您正在使用的课程提供其中一种方法,则只能按照您的建议行事。例如,+ [NSString stringWithFormat:...]采用可变数量的参数。 Cocoa提供 - [NSString initWithFormat:arguments:]其中arguments参数是va_list。这允许您执行以下操作:

- (void)setContentsWithFormat:(NSString *)formatString, ... {
    [contents autorelease];

    va_list args;
    va_start(args, formatString);
    contents = [[NSString alloc] initWithFormat:formatString arguments:args];
    va_end(args);
}

va_list参数允许我们将自己的变量参数列表传递给Cocoa方法,以便Cocoa方法可以处理参数。

但是,由于UIAlertView不提供va_list API,最简单的方法可能是重复调用addButtonWithTitle:

答案 1 :(得分:2)

你做不到。 Objective-C的变量参数支持实际上是C的支持,并且您可能已经知道没有(可移植的)方法来正确设置堆栈以调用可变参数函数。

如果超类的设计者在球上,那么会有一个并行函数,它接受一个va_list或NSArray参数。如果没有,你通常会运气不好。

在这种特殊情况下,您可以使用nil为所有按钮调用超类的构造函数,然后使用addButtonWithTitle:cancelButtonIndex等来“手动”设置按钮

答案 2 :(得分:0)

如果你不能以正确的方式做到这一点,你可以随时这样做:

id arg1 = ...; // nil or 1st arg
id arg2 = ...; // nil or 2nd arg
id arg3 = ...; // nil or 3rd arg
id arg4 = ...; // nil or 4th arg
// etc.

self = [super initWithTitle:title
                   delegate:delegate
          cancelButtonTitle:cancelButtonTitle
     destructiveButtonTitle:destructiveButtonTitle
          otherButtonTitles:arg1,arg2,arg3,arg4,/*etc*/ nil];

丑陋,但它会起作用。