UIActionSheet取消按钮的奇怪行为

116

我有一个UIBarButtonItem,它会打开一个操作表,让用户选择要做什么。除非我试图单击"取消"按钮,否则一切都按预期工作。该按钮的目标似乎已经从其原来应该在的位置上移动了。我只能通过在"取消"和"确定"按钮的中间某处单击来激活它。

我尝试了其他应用程序中的操作表,它们正常工作,所以这不仅仅是我的手指太大了。该操作表正在UIViewController中打开。

- (void)showOpenOptions
{
    UIActionSheet *sheet = [[UIActionSheet alloc] 
    initWithTitle:NSLocalizedString(@"Open link in external application?", @"Open in external application")
    delegate:self
    cancelButtonTitle:NSLocalizedString(@"Cancel", @"Cancel")
    destructiveButtonTitle:NSLocalizedString(@"Open Link", @"Open Link")
    otherButtonTitles:nil];

    [sheet showInView:self.view];
    [sheet release];
}

5
顺便提一下,我在苹果用户界面审查会议上被告知,操作表中的红色按钮实际上是用于“破坏性”操作(即“删除”)。 - Ramin
是的,我最近阅读了人机界面指南并看到了这一点。将它从红色改为灰色了。 - nevan king
7个回答

190

不要将当前视图控制器的视图传递给操作表,而是使用UIActionSheetshowFromTabBar:方法。

正确的方式
这将提供正确的可点击区域:

[actionSheet showFromTabBar:self.tabBarController.tabBar];

错误的方式
如果你正在使用选项卡栏或工具栏,则这将把可点击区域放错位置:

[actionSheet showInView:self.view];

如果您使用的是工具栏,请改用showFromToolbar:方法。您需要一个工具栏的引用,很可能是一个实例变量。

[actionSheet showFromToolbar:self.myToolbar];

我的旧答案也有效,但是有点hacky:

刚找到一个可能的答案:

2008年12月1日晚上10:22 Tom Saxton: 我仔细研究了这个bug,它似乎是与选项卡栏有关的问题。

如果您从UITabViewController的子视图控制器中调用UIActionSheet的[sheet showInView:self.view],则在UIActionSheet中位于选项卡栏视图上方的部分中,取消按钮的命中测试失败。

如果您改为传递UITabBarController的视图,则UIActionSheet会按预期工作。

注意:在iPhone OS 2.1及更早版本中,当您传递子视图时,UIActionSheet会从选项卡栏顶部弹出,但在2.2中,它会从选项卡栏底部弹出,从而覆盖选项卡视图。

http://openradar.appspot.com/6410780

编辑:当我将视图更改为选项卡栏的视图时,它可以正常运行。

[sheet showInView:self.parentViewController.tabBarController.view];

1
为什么需要parentViewController?即使视图在navigationview tabBarController中,也应该指向正确的位置。在任何情况下,没有parentViewController对我来说都可以工作。 - Nathan
11
另一个答案似乎更好。请查找[actionSheet showInView:[self.view window]]。似乎更直接和更通用。 - Kevin
非常感谢您发布这个答案。 - fulvio
1
我的应用程序中没有选项卡栏,但仍然遇到了这样的问题。我使用 '[serf.view window]' 解决了它。无论如何,这不是选项卡栏的问题。 - Mike Keskinov
我已经点赞了,但是我仍然有关于目标区域问题的疑问。不过取消按钮现在对我来说运行良好。 - Pradeep Mittal
显示剩余2条评论

37

我在这里找到了一个有效的答案。

使用:[filterActionSheet showInView:[self.view window]];

我尝试了几种方法来获取我的标签栏,但是由于该应用程序的设置很复杂,所以似乎很困难...


太完美了!谢谢。对于我来说,这是正确的解决方案,因为我使用的UITableViewController有一个工具栏而不是像其他人那样的选项卡栏。 - William Denniss
好东西,这对我有用!这绝对是最简单的方法! - Christian Gossain
2
它引起了另一个问题。当设备处于横向模式时(以及所有其他内容),ActionSheet会以纵向方向出现。 - Mike Keskinov

22

请改用:

[sheet showFromTabBar:theTabBar];

1
我将showInTabBar:更正为showFromTabBar:。另外请注意,根据屏幕底部的工具栏类型,可能会有showFromToolbar:方法。我认为这是比被接受的答案更好的解决方案。 - Stephen Darlington
Stephen,我很好奇你为什么认为这比指定showInView:theTabBar更好?从耦合的角度来看,我认为showInView可能更理想,以防以后tabBar被取消了,也许会被工具栏替换。特定的子视图控制器真的不需要知道或关心这个,我认为。 - Billy Gray
如果标签栏稍后被删除,您将不得不编辑该行代码(除非theTabBar是对传递的视图的误命名引用)。因此,我不认为这种方法比showInView:theTabBar更紧密耦合。我也使用showFromTabBar:,因为它对我来说似乎更安全。我不知道在幕后发生了什么,但我想showFromTabBar:比具有选项卡栏视图的showFromView:在未来的操作系统版本中更不容易出现问题。 - Christopher Pickslay

10

以下是修复方法。请尝试执行以下操作:

[actionsheet showInView:[UIApplication sharedApplication].keyWindow];

5

我认为综合三个答案的方法是正确处理此事的方式:

    [actionSheet showFromTabBar:self.tabBarController.tabBar];

即使用showFromTabBar(这就是它的存在原因),并且您不需要像Nathan所指出的那样使用parentViewController(实际上,self.parentViewController.tabBarController.tabBar对我而言返回nil)。


当然它会返回nil,因为父视图控制器(即UITabBarViewController)本身并没有嵌套到另一个UITabBarController中,所以它的tabBarController属性是nil。 - Dominik Seibold

1

提醒一下 - 我也遇到了UIDocumentInteractionController的操作表格覆盖了选项卡栏的问题。使用以下方法解决。

UIViewController *parentView = [[self parentViewController] parentViewController];
[docController presentOptionsMenuFromRect: rect inView: parentView.view animated:YES];

-2

编写简单的代码

 actionSheet.actionSheetStyle = UIActionSheetStyleDefault;

这个工作得很好


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