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

发布于 2024-10-29 18:01:42 字数 1355 浏览 1 评论 0原文

OS X 开发人员库在以下技术文章中展示了如何创建采用可变数量参数的方法:http://developer.apple.com/library/mac/#qa/qa1405/_index.html

我试图弄清楚是否可以对采用变量参数的现有方法实现进行子类化并调用超类实现。

使用 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 而是使用 va_list、va_start、va_end 创建一个字符串数组并多次调用 addButtonWithTitle: ,我知道我可以我使用 UIActionSheet 作为示例。在其他情况下,使用变量 args 子类化方法会很有用,我想了解如何准确地执行我所要求的操作,

谢谢!

The OS X Developer Library shows how to create a method that takes a variable number of args in the following technical article: http://developer.apple.com/library/mac/#qa/qa1405/_index.html.

I'm trying to figure out if it's possible to subclass an existing implementation of method that takes variable args and call the superclass implementation.

Using UIActionSheet as an example look at the code below. Calling the superclass initWithTitle method only passes the first 'otherButtonTitle'. I don't know how to pass the remaining strings contained in the variable argument list.

// 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;
}

I can get the args using va_list, va_start, va_end but don't know how to pass them to the superclass method.

In case anyone is tempted to tell me that I can do this a different way (e.g. don't pass along the variable args but use va_list, va_start, va_end to create an array of strings and call addButtonWithTitle: multiple times, I know I can do that. I used UIActionSheet as an example. There are other cases where the ability to subclass a method with variable args would be useful and I'd like to learn how to do exactly what I've asked if it is possible.

thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

勿忘初心 2024-11-05 18:01:42

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:

A number of classes in Cocoa have methods that take variable numbers of arguments. In most cases, these classes will also have an equivalent method that takes a va_list. It's only possible to do what you're suggesting if the class you're using provides one of those methods. For instance, +[NSString stringWithFormat:...] takes a variable number of arguments. Cocoa provides -[NSString initWithFormat:arguments:] where the arguments parameter is a va_list. This allows you to do the following:

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

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

The va_list parameter allows us to pass our own variable argument list to the Cocoa method so that the Cocoa method can handle the arguments.

However, since UIAlertView doesn't provide a va_list API, the cleanest way is probably to make repeated calls to addButtonWithTitle:

画中仙 2024-11-05 18:01:42

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

如果超类的设计者很聪明,就会有一个并行函数,它接受一个 va_list 或 NSArray 参数,您可以调用它。如果没有,你通常会不走运。

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

You can't. Objective-C's variable arguments support is effectively that of C, and as you may already know there is no (portable) way to correctly set up the stack to call to a variadic function.

If the designer of the superclass was on the ball, there will be a parallel function that takes a va_list or NSArray argument that you can call instead. If not, you're usually out of luck.

In this particular case, you could call the superclass's constructor with nil for all the buttons, and then use addButtonWithTitle:, cancelButtonIndex, and so on to setup the buttons "manually".

梦忆晨望 2024-11-05 18:01:42

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

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];

丑陋极了,但它会起作用。

If you can't do it the proper way, you can always do this:

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];

ugly as hell, but it will work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文