模态视图控制器出现在操作表后面

Posted

技术标签:

【中文标题】模态视图控制器出现在操作表后面【英文标题】:Modal View Controllers appear behind Action Sheet 【发布时间】:2010-12-15 18:15:48 【问题描述】:

我的模式视图控制器显示在我的 UIActionSheet 后面,并且我的 UIActionSheet 没有被关闭。我正在使用:

[self presentModalViewController:composeTweetView animated:YES];

展示我的模态视图控制器。

我的操作表正在从 tabBar 显示:

[actionSheet showFromTabBar:self.parentViewController.tabBarController.tabBar];

此代码适用于 ios 4.0。

if (buttonIndex == 0) 
        if (self.isLoggedIn) 
            [FlurryAPI logEvent:@"ST_REPLY_CLICKED"];
            composeTweetView.isDirectMessage = FALSE;
            [self presentModalViewController:composeTweetView animated:YES];
            [composeTweetView release];
        
        else 
            LoginViewController* loginView = [[LoginViewController alloc] initWithNibName:@"LoginViewController" bundle:nil];
            loginView.delegate = self;
            loginView.isPostingComment = TRUE;
            self.isReply = TRUE;
            [self presentModalViewController:loginView animated:YES];
            [loginView release];
            [composeTweetView release];
        
    

总结:

我有一个包含 UITabBar 的 UIViewController。我正在展示一个 UIActionSheet,它有几个按钮来展示一个模态视图控制器。当模态视图控制器出现时,UIActionSheet 应该自行关闭,并且模态视图应该位于堆栈的顶部。问题是, UIActionSheet 没有关闭,并且在它后面加载了模态视图。这个问题直到 iOS 4.2.1 才出现

复制步骤:

    创建一个TabBar项目,设置 你的基础 SDK 到 iOS 4.2.1 创建按钮或触发器以显示 UIActionSheet 允许 UIActionSheet 中的一个按钮使用以下语法呈现模式视图控制器:[actionSheet showFromTabBar:self.parentViewController.tabBarController.tabBar];

预期结果:

1. The UIActionSheet should dismiss itself, and the modal view should appear in front

实际结果:

1. The UIActionSheet does not get dismissed and the modal view appears behind it.

回归:

This problem was not apparent prior to iOS 4.2.1

注意事项: 我尝试了其他显示 UIActionSheet 的方法,所有这些都无法按预期工作:

//[actionSheet showInView:self.parentViewController.tabBarController.tabBar];
//[actionSheet showInView:[self.view window]];
//[actionSheet showInView:self.parentViewController.tabBarController.view];
//[actionSheet showInView:[UIApplication sharedApplication].keyWindow];

【问题讨论】:

它在 4.2 中工作吗?实际上我在 4.2 中测试了该应用程序,它运行良好。 适用于 4.2。不适用于 4.2.1 你从哪里得到 4.2.1?在我的 DevCenter 中,最新的 XCode 来自 11 月 22 日,包含 4.2 而不是 4.2.1 还有一件事,随着 iOS SDK 的每个增量而损坏/脆弱。 【参考方案1】:

为了重现您的问题,我整理了一个示例,查看了 UIActionSheet 委托方法。我相信你可以使用:

actionSheet:didDismissWithButtonIndex:

而不是

actionSheet:clickedButtonAtIndex:

我尚未对其进行测试,但我相信您仍然会得到相同的按钮编号,并且在操作表从视图中消失之前它不会触发。

【讨论】:

我使用的唯一委托方法是:-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 我需要手动关闭操作表吗? 仍然没有运气 :( 使用新的委托方法【参考方案2】:

抱歉,我不明白您的问题,但一切对我来说都很好。我在模拟器和 4.2.1 iPod Touch 4G 上尝试了以下代码(都有效)

- (IBAction)doit 
    UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"title" delegate:self cancelButtonTitle:@"not OK" destructiveButtonTitle:@"Absolutely" otherButtonTitles:nil];
    [actionSheet showFromTabBar:self.tabBarController.tabBar];
    [actionSheet release];


- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 
    if (buttonIndex == 0) 
        UIView *v = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
        v.backgroundColor = [UIColor redColor];
        [self.view addSubview:v];
        [v release];
    

    创建了 TabBar 示例项目 将按钮添加到 firstView-nib 并与相应的 IBAction 连接(必须将 FileOwner 命名为 FirstViewController) 在FirstViewController.h<UIActionSheetDelegate>)中设置委托方法 添加了上面的代码

//编辑:好的,我看到您想以模态方式呈现它,但即使这在 4.2.1 上也适用于我

TMPController *tmp = [[TMPController alloc]initWithNibName:@"TMP" bundle:nil];
[self presentModalViewController:tmp animated:YES];
[tmp release];

可能因为我用self.tabBarController.tabBar所以可以,试试吧

【讨论】:

所以试试 self.tabBarController.tabBar 的东西 ;) [actionSheet showFromTabBar:self.parentViewController.tabBarController.tabBar]; //没有运气 hmm 真奇怪,你用的是什么设备?因为在我的 iPod Touch 4G iOS 4.2.1 (8C148) 上它按预期工作。尝试使用其他设备或其他 XCode 环境 我正在使用 iPhone 4 进行测试【参考方案3】:

不确定您是否已经解决了这个问题。但我没有在上面看到明确的答案。我和你有完全一样的问题。所以最后,这是我这边的一个问题,但帮助我调试的是在方法中添加实际的操作代码

actionSheet:didDismissWithButtonIndex: 

按照 Matthew 的建议。

这证明了这个观点实际上被驳回了。那时我意识到我将 UIActionSheet alloc 放在了 viewWillAppear 方法中。因此,每次视图出现时,它都会重新创建操作表。

【讨论】:

【参考方案4】:

正如 SDK 文档所述,这看起来很奇怪:

actionSheet:clickedButtonAtIndex: … 调用此方法后,接收方会自动关闭。

我能想到它可能不会消失的 3 种可能性:

    不调用处理动画和显示内容的主运行循环(主线程!)。您是否在主线程中处理过繁重的工作,例如同步网络调用? (注意 SDK 文本中的“之后”一词) 您计划以某种方式多次显示操作表 您以模态方式显示相同的视图控制器实例,该实例已经位于视图堆栈中当前视图下方的某个位置。

【讨论】:

我没有阻塞运行循环,一切都是异步的,动作表只被调用一次,与模态视图控制器一起,没有多个实例。奇怪的是,自从我在 iOS 3.0 上构建以来,这一直有效......【参考方案5】:

我刚刚编写了一个快速示例应用程序来测试它,它的工作方式与我预期的一样(即,我无法重现您的问题)。 有点不同,因为我没有做 TabBar 应用程序,但我仍然希望这会有所帮助。我对UIActionSheet 所做的就是这样展示它:[actionSheet showInView:self.view]。也许这会起作用?

抱歉,我的回答太仓促了,我正要出去的时候,这引起了我的注意。 :)

【讨论】:

[actionSheet showInView:self.view] 不幸地对我不起作用。相同的结果。奇怪的是我的代码如何在除 iOS 4.2.1 之外的所有版本上运行【参考方案6】:

我在 iOS 4.2 上也遇到过类似的问题。 我认为您应该尝试以下步骤:

    为您希望在单击操作表按钮时执行的代码创建一个单独的方法。假设方法是 -(void)presentModalView

2.现在在-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex方法中,为被点击的对象调用presentModalView方法像这样的按钮索引:

if(buttonIndex==0)

[self performSelector:@selector(presentModalView) withObject:nil afterDelay:0.3];

3.您也可以尝试不同的延迟时间。

希望对你有帮助..

【讨论】:

运气不好。仍然显示在操作表后面,不会被关闭。 很抱歉..无法帮助您..但我还没有将我的 iOS 4.2 更新到 4.2.1。因此,无法重现该问题。【参考方案7】:

我从 AlertBox/ActionSheet 调用 MailComposeView 时遇到了同样的问题,导致 MailCompseView 出现在不可见的屏幕后面。

我通过在 actionSheet 按钮处理程序中调用 dismissWithClickedButtonIndex:animated: 解决了这个问题。

【讨论】:

我在处理程序中尝试了 dismissWithClickedButtonIndex:animated: 但没有运气【参考方案8】:

iOS5 已解决该问题。

【讨论】:

以上是关于模态视图控制器出现在操作表后面的主要内容,如果未能解决你的问题,请参考以下文章

如何在模态呈现的视图控制器上执行呈现模态序列?

模态视图控制器优于呈现视图控制器

iOS 7:出现模态视图控制器时限制设备当前方向

防止出现第二个模态视图?

视图控制器以模态方式呈现/关闭时的通知?

iPad上的模态表单视图控制器 - 淡入黑色