在iOS8 - iOS11中从动作表的委托中以模态方式呈现视图控制器

时间:2014-07-20 20:52:16

标签: ios uikit uiactionsheet uialertcontroller

所以我注意到在iOS上的iOS8 beta 3(更新:仍然在iOS 11.2中发生),尝试在UIActionSheet的委托方法中呈现视图控制器时, "无"发生并将日志消息输出到调试控制台,说明在转换警报控制器时尝试了演示:

Warning: Attempt to present <UIViewController: 0x...> on <ViewController: 0x...> which is already presenting <UIAlertController: 0x...>

9 个答案:

答案 0 :(得分:138)

更新:从iOS 9 SDK开始,UIActionSheet已弃用,因此不要指望针对此问题进行修复。最好在可能的情况下开始使用UIAlertController


问题似乎来自Apple在内部使用UIAlertController来实现警报视图和操作表的功能。这个问题主要出现在iPad和操作表上,因为在iPad上,操作表在指定视图中显示为弹出窗口,而Apple所做的就是在响应者链中行进,直到找到视图控制器并调用presentViewController:animated:completion:为止内部UIAlertController。问题在iPhone和警报视图上不那么明显,因为Apple实际上创建了一个单独的窗口,一个空的视图控制器并在其上面显示内部UIAlertController,因此它似乎不会干扰其他演示。< / p>

我已针对此问题打开了错误报告: rdar:// 17742017 。请复制它,让Apple知道这是一个问题。

作为一种解决方法,我建议使用以下方法将演示文稿延迟到下一个runloop:

dispatch_async(dispatch_get_main_queue(), ^ {
    [self presentViewController:vc animated:YES completion:nil];
});

答案 1 :(得分:31)

您可以尝试在

中完成工作(呈现视图控制器)
- (void)      actionSheet:(UIActionSheet *)actionSheet
didDismissWithButtonIndex:(NSInteger)buttonIndex {}

而不是

- (void) actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {}
@LeoNatan说,&#34;问题似乎来自Apple在内部使用UIAlertController来实现警报视图和操作表的功能&#34; 。因此,您必须等待操作表被解除,然后呈现您想要的视图控制器。

@LeoNatan的解决方案只是在主线程中阻止UI,因此它还确保在操作表被解除后显示视图控制器。

答案 2 :(得分:4)

遗憾的是,这段代码对我来说并不起作用,我认为因为我的问题不是直接调用presentController方法,而是在prepareForSegue方法中使用

[segue destinationViewController]

我注意到如果segue是&#34;推&#34;一切都正常,但如果它是&#34; modal&#34;,只是在ipad中,我得到了那个错误。

然后我在segue面板中的故事板中找到了一些新选项,并且我选择了#34;当前环境&#34; for Presentation选项

我希望这对其他人有帮助... 这是关于选项

的屏幕截图

enter image description here

答案 3 :(得分:2)

我有同样的问题。我在appdelegate中为警报和操作表创建了一个单独的窗口,并在其上显示警报。它对我有用!

   self.alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
  // Override point for customization after application launch.
  self.alertWindow.backgroundColor = [UIColor clearColor];
  UIViewController *dummy = [[UIViewController alloc] init];
  [self.alertWindow setRootViewController:dummy];

你可以表现为:

[[myAppDelegate appDelegate].alertWindow makeKeyAndVisible];
  [[myAppDelegate appDelegate].alertWindow.rootViewController presentViewController:alertController animated:YES completion:nil];

答案 4 :(得分:2)

我使用以下代码

在Swift 3中修复它
  DispatchQueue.main.async {
            self.present(alertController, animated: true, completion: nil)
        }

答案 5 :(得分:1)

发布

[self.navigationController dismissViewControllerAnimated:YES completion:nil];

on

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 

在尝试呈现另一个模态视图之前为我工作。

答案 6 :(得分:1)

使用

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex

而不是

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

动作视图显示在当前VC之上,因此导致警告/错误。 当调用didDismiss时,动作视图已被解除,因此根本没有问题:))

答案 7 :(得分:0)

尝试

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    // action sheet presentation
    // or modal view controller presentation
    // or alert view presentation
}];

答案 8 :(得分:0)

在iOS 8中,Apple在内部使用UIAlertController来实现警报视图和操作表的功能。所以当你想在委托方法中显示UIActionSheet或UIAlertView之后以模态方式显示UIViewController,如

(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex

(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

你必须首先解雇UIAlertController,如下所示:

if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0"))
{
    UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
    [vc dismissViewControllerAnimated:NO completion:^{

    }];
}

现在你可以在iOS 8中呈现一个模态UIViewController。