在iOS8 – iOS10中从操作表代表以模态方式呈现视图控制器

所以我注意到,在iPad上,当试图从UIActionSheet的委托方法中呈现视图控制器时,在iOS8 beta 3( 更新 :仍然发生在iOS 10中)上,“nothing”发生并且日志消息被输出到debugging控制台,表示在转换警报控制器的过程中尝试了演示文稿:

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

更新:在iOS 9 SDK中, UIActionSheet已被弃用,所以不要指望修复这个问题。 如果可能,最好开始使用UIAlertController


这个问题似乎来自苹果切换到内部使用UIAlertController来实现警报视图和操作表的function。 这个问题主要出现在iPad和动作表上,因为在iPad上,动作表是作为指定视图内的popup窗口显示的,而苹果所做的就是presentViewController:animated:completion:响应者链,直到find视图控制器并调用presentViewController:animated:completion:与内部UIAlertController 。 这个问题在iPhone和alert视图上不太明显,因为Apple实际上创build了一个单独的窗口,一个空的视图控制器,并在其上面显示了内部UIAlertController ,所以它似乎不会干扰其他演示。

我已经打开这个问题的错误报告: rdar:// 17742017 。 请复制它,让苹果知道这是一个问题。

作为一种解决方法,我推荐使用以下方法来延迟演示,直到下一个runloop:

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

你可以尝试做你的工作(呈现视图控制器)

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

代替

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

正如@LeoNatan所说: “这个问题似乎来自苹果公司内部使用UIAlertController来实现警报视图和操作表的function” 。 所以你必须等待行动表被解散,然后呈现你想要的视图控制器。

@LeoNatan的解决scheme就是在主线程中阻止用户界面,所以它也会确保视图控制器在操作表被解除后呈现。

不幸的是这个代码不适用于我,我想因为我的问题不是直接调用presentController方法,而是在prepareForSegue方法中,所以使用

 [segue destinationViewController] 

我注意到,如果segue是“推”类的所有工作正常,但如果它是“模态”,只是在iPad中,我得到了这个错误。

然后,我在segue面板的storyboard中find了一些新的选项,并且我select了“Current context”作为Presentation选项

我希望这将有助于别人…这是关于选项的截图

在这里输入图像说明

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

  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]; 

发出一个

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

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

然后尝试呈现另一种模式的看法为我工作。

使用

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

代替

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

动作视图是在当前的VC上方呈现的,因此是什么导致警告/错误。 当didDismiss被调用时,动作视图已经被解散,所以没有任何问题:))

我使用下面的代码在Swift 3中修复了它

  DispatchQueue.main.async { self.present(alertController, animated: true, completion: nil) } 

尝试

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

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

 (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。