使用超过6个自定义按钮时,UIActionSheet的buttonIndex值出现故障?

25

我在使用iPhone(iOS 4.2)上的UIActionSheet时发现了一个奇怪的问题。看一下这段代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    [self.window addSubview:viewController.view];
    [self.window makeKeyAndVisible];

    UIActionSheet *actionSheet = [[UIActionSheet alloc] 
                                  initWithTitle:@"TestSheet" 
                                  delegate:self 
                                  cancelButtonTitle:@"Cancel" 
                                  destructiveButtonTitle:nil 
                                  otherButtonTitles: nil];

    [actionSheet addButtonWithTitle:@"one"];
    [actionSheet addButtonWithTitle:@"two"];
    [actionSheet addButtonWithTitle:@"three"];
    [actionSheet addButtonWithTitle:@"four"];
    [actionSheet addButtonWithTitle:@"five"];
    [actionSheet addButtonWithTitle:@"six"];
    //uncomment next line to see the problem in action
    //[actionSheet addButtonWithTitle:@"seven"];

    [actionSheet showInView:window];
    [actionSheet release];

    return YES;
}
- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    NSLog(@"buttonIndex: %d, cancelButtonIndex: %d, firstOtherButtonIndex: %d",
          buttonIndex, 
          actionSheet.cancelButtonIndex, 
          actionSheet.firstOtherButtonIndex);
}
如果你启动这个应用程序,操作表将按预期工作。这意味着cancelButtonIndex始终为0,并且按钮索引被正确报告。其中一个按钮是1,等等。如果您注释第七个按钮添加的行,则操作表会生成一种类似于tableView的表格,取消按钮会出现在额外一行上。在这种情况下,如果我按“one”按钮,则buttonindex变量为0,而cancelButtonIndex也是0。无法确定用户是否点击了“取消”或“one”按钮。这看起来不应该是这样的。有人持反对意见吗?感谢您的帮助。

动作表上有六个按钮?真的吗?我建议使用表格来展示选项... - Eimantas
9
如果你不打算使用能够在滚动视图中处理超过6个按钮的操作表,那么它的存在意义是什么? - huesforalice
遇到了同样的问题,显然是一个bug。 - Ege Akpinar
令人惊讶的是,这个错误 - 显然是一个错误 - 在iOS 7.0+版本中仍然存在。 - Christopher King
5个回答

34

尽管我已将取消按钮作为操作表的最后一个按钮,并相应地设置了它的索引,但我仍然遇到了相同的问题。我的问题与“破坏性”按钮有关。经过一些调查,我对问题的看法如下:

  • 在添加了N个按钮到操作表后,它会切换布局,将“破坏性”按钮放在顶部,将取消按钮放在底部。中间是一个可滚动视图,包括所有其他按钮。其他来源指出这是一个表视图。

  • 在纵向方向上,N为7,在横向方向上,N为5。在较大的4英寸屏幕上,N在纵向方向上为9。这些数字都包括取消和破坏性按钮。要明确的是,N是在切换前最大的按钮数。添加N+1个按钮会导致UIActionSheet切换到可滚动视图。

  • 无论您最初将取消和破坏性按钮放在操作表的位置如何,一旦达到限制,破坏性按钮就会移到顶部,取消按钮就会移到底部。

  • 问题在于索引没有相应地进行调整。因此,如果您最初没有将取消按钮添加为最后一个按钮,将破坏性按钮添加为第一个按钮,那么在actionSheet:clickedButtonAtIndex:中报告的索引将是错误的,就像最初的报告所述。

  • 因此,如果您要在操作表中有多于N个按钮,必须将破坏性按钮作为操作表的第一个按钮添加到操作表中。您必须将取消按钮作为添加到操作表中的最后一个按钮。在最初构建表时,将两者都留空,如另一个答案中所述。


1
这是实际上正确的答案 - 不是上面标记的那个。感谢Rich的发布。对于读者来说,请注意第四个项目关于按钮排序的问题。 - Christopher
5
这种行为太荒谬了。我常常想知道为什么苹果会做出某些决定,这就是其中之一。感谢这个提示。 - stephenmuss

13

我刚遇到了这个问题。解决方法是最初不设置取消按钮。我单独设置了按钮,像这样:

   for(int index = 0; index < buttonTotal; index++)
   {
    [actionSheet addButtonWithTitle:[NSString stringWithFormat:buttonText, [buttonItems objectAtIndex: index]]];
   }

   [actionSheet addButtonWithTitle:@"Cancel"];
   actionSheet.cancelButtonIndex = actionSheet.numberOfButtons;

我相信如果你使用destructiveButton,零索引会被使用,所以其他按钮将从那里递增,否则它们将从0开始。

对于表格选项,我不确定是否同意,因为在某个数量级以上,按钮默认为可滚动列表。


18
你应该只需执行 actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:@"Cancel"]; 的操作。 - user102008
本地化会破坏这种解决方案吗? - Ege Akpinar
我曾认为本地化会破坏这个解决方案(因为不同语言环境中的“取消”字符串不同)。刚刚实施了@user102008的解决方案,它可以无问题地运行(它必须基于索引而不是字符串来确定取消按钮)。 - Ege Akpinar

1

提交错误报告以解决问题。请包含一个小的示例项目,并等待数月时间等待他们的回复。

目前,您可以在init中静态设置按钮。

UIActionSheet *actionSheet = [[UIActionSheet alloc] 
                              initWithTitle:@"TestSheet" 
                              delegate:self 
                              cancelButtonTitle:@"Cancel" 
                              destructiveButtonTitle:nil 
                              otherButtonTitles: @"one", @"two", @"three", @"four", @"five", @"six", @"seven", nil];

没有问题,正常运行。


谢谢您的提示,不过我需要从一个数组中设置按钮,上面提到的只是一个示例,指出 addButtonWithTitle 方法似乎不起作用。 - huesforalice

1

1) 使用以下代码实例化 actionview:

[[UIActionSheet alloc] initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:]

取消按钮和破坏性按钮都设置为 nil。

2) 使用 [myActionSheet addButtonWithTitle:(NSString *)] 添加所有按钮。

3) 如果您需要一个特殊的按钮,使用与步骤 2 相同的方法添加它,并将标题设置为任何内容(例如 @"Cancel")。

4) 现在将属性 [myActionSheet setCancelButtonIndex:] 设置为 actionsheet 上最后一个按钮的索引,该按钮是取消按钮。对于破坏性按钮也是如此。(默认情况下为 -1,这会导致它们不显示)

请注意,破坏性按钮将始终显示在顶部,取消按钮将始终显示在底部,无法更改。 此外,您可以在索引0处添加取消/破坏性按钮,并在其后添加所有其他按钮。但是,现在您的其他按钮的第一个索引是1,而不是零。如果您有与alertview按钮对应的数组,则可能会引起混淆。

0

请按照以下方式操作:

UIActionSheet *actionSheet = [[UIActionSheet alloc] 
                              initWithTitle:@"TestSheet" 
                              delegate:self 
                              cancelButtonTitle:@"Cancel" 
                              destructiveButtonTitle:@"Delete" 
                              otherButtonTitles: @"one", @"two", @"three", @"four", @"five", @"six", @"seven", @"eight", nil];

这意味着将破坏性按钮定义为destructiveButtonTitle。避免在otherButtonTitles中使用破坏性/取消按钮。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接