UIAlertView 的转发可变参数

Posted

技术标签:

【中文标题】UIAlertView 的转发可变参数【英文标题】:Forward variadic arguments for a UIAlertView 【发布时间】:2014-09-29 14:48:43 【问题描述】:

我正在尝试设置一个非常简单的UIAlertView,带有一个文本编辑、一个确定和一个取消按钮,我想根据文本编辑的内容禁用确定按钮。

为了能够保留委托,这样他就不会在警报视图之前离开(因此一旦用户对警报视图执行某些操作就会导致崩溃),我将其子类化。现在,我希望能够将 otherButtonTitles 参数从我的 init 方法转发到 UIAlertView init 方法,但出于某些原因,只需这样做:

- (id)initWithTitle:(NSString *)title
            message:(NSString*)message
           delegate:(id /*<UIAlertViewDelegate>*/)delegate
  cancelButtonTitle:(NSString *)cancelButtonTitle
  otherButtonTitles:(NSString *)otherButtonTitles, ... 

    if (self = [super initWithTitle:title 
                            message:message 
                           delegate:delegate 
                  cancelButtonTitle:cancelButtonTitle 
                  otherButtonTitles:otherButtonTitles, nil]) 
        //stuff
    

只将 args 的第一个元素添加到警报视图中。我发现我实际上可以使用以下方法手动将按钮添加到警报视图:

va_list args;
va_start(args, otherButtonTitles);
for (NSString *buttonTitle = otherButtonTitles; buttonTitle != nil; buttonTitle = va_arg(args, NSString*)) 
  [self addButtonWithTitle:buttonTitle];

va_end(args);

但是,我的 alertViewShouldEnableFirstOtherButton 委托方法不再被调用,with the probable explanation in this post

因此,我怎样才能正确地将我的otherButtonTitles 转发到UIAlertView init 方法?

【问题讨论】:

我总是被这样一个事实困扰,在 C 中你可以使用 va_list 收集可变参数,但无法将它进一步传递给另一个可变参数函数。我们知道 abi 和 bounds,但不知道。 顺便说一句,如果您熟悉 objc 运行时 (objc_msgSend),并确保其他按钮的数量永远不会超过某个固定限制,您可以使用此处描述的 hack:c-faq.com/varargs/handoff.html @user3125367 感谢您的链接,但这在这里完全不可行,因为我受到UIAlertView init 方法签名的约束,该方法不需要 va_list 而是可变参数... 不确定您是否错过了页面底部的非常错误的解决方案。它以非常错误的方式解决了这个问题 :) 但它应该可以工作。 是的,不,我想避免这种方式...... 【参考方案1】:

那么让我们减少击键次数:

NSMutableArray *otherButtonTitles = [NSMutableArray array];
// .. collect varargs into ^^^

#define T(n) ([otherButtonTitles objectAtIndex:n])
#define CASE(n, ...) case n: self = [super initWithTitle:title \
                                                 message:message \ 
                                                delegate:delegate \
                                       cancelButtonTitle:cancelButtonTitle \
                                       otherButtonTitles:__VA_ARGS__, nil]; \
                             break

switch ([otherButtonTitles count]) 
    CASE(0, nil);
    CASE(1, T(0));
    CASE(2, T(0), T(1));
    CASE(3, T(0), T(1), T(2));
    // ... repeat until bored ...
    default: @throw @"too many buttons"; // or return nil

【讨论】:

以上是关于UIAlertView 的转发可变参数的主要内容,如果未能解决你的问题,请参考以下文章

如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?

可变参数模板

如何对可变参数函数中的所有参数调用 std::forward ?

c ++ lambdas如何从上层范围捕获可变参数包

如何调用所有可变继承类的函数?

可变参数