【问题标题】:Presenting a view controller modally from an action sheet's delegate in iOS8 - iOS11从 iOS 8 - iOS11 中的操作表委托以模态方式呈现视图控制器
【发布时间】:2014-09-11 08:24:58
【问题描述】:

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

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

【问题讨论】:

    标签: ios uikit uiactionsheet uialertcontroller


    【解决方案1】:

    更新:从 iOS 9 SDK 开始,UIActionSheet 已被弃用,因此不要指望修复此问题。最好尽可能开始使用UIAlertController


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

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

    作为一种解决方法,我建议使用以下方法将演示延迟到下一个运行循环:

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

    【讨论】:

    • 即使这样对我也不起作用。弹出窗口失败。 iOS8 = 破坏了一切。
    • @Michael 弹出框失败是什么意思?
    • 很难想象这个错误仍然存​​在。 @leo-natan 你有来自 Apple 的更新吗?
    • @Pichirichi 不,这个问题仍然存在于 Apple 中,并在 8.1 b1 上重现。
    • 此解决方法适用于 iPad、iOS 8.1b2 上的 UIActionSheetshowFromRect:
    【解决方案2】:

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

    [segue destinationViewController]
    

    我注意到如果 segue 是“push”类型的,一切正常,但如果它是“modal”,就在 ipad 中,我得到了那个错误。

    然后我在 segue 面板的情节提要中找到了一些新选项,我解决了为演示选项选择“当前上下文”的问题

    我希望这对其他人有帮助... 这是有关该选项的屏幕截图

    【讨论】:

      【解决方案3】:

      您可以尝试在

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

      而不是

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

      正如@LeoNatan 所说,“问题似乎来自 Apple 转而在内部使用 UIAlertController 来实现警报视图和操作表的功能”。因此,您必须等待操作表关闭,然后呈现您想要的视图控制器。

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

      【讨论】:

      • 我的解决方案没有阻塞主线程。在 didDismiss 中呈现会导致同样的问题。
      • @LeoNatan “在 didDismiss 中呈现会导致同样的问题”,你的意思是仍然无法解决问题?嗯..但我把它修好了,一旦操作表被解除,视图控制器就会出现:)
      • @LeoNatan hm.. "block" 的意思是你的 "将演示延迟到下一个 runloop" ;)
      • @HernanArber 是的,我有很多关于 iOS 8 SDK 的 WHY。
      • 这似乎是最好的解决方案,我觉得结果也更自然。
      【解决方案4】:

      发布一个

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

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

      在尝试呈现另一个对我有用的模式视图之前。

      【讨论】:

      • 嗨,欢迎来到 stackoverflow!请将您的答案格式化为更易读的格式,并尽可能提供更多解释。
      【解决方案5】:

      使用

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

      而不是

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

      操作视图显示在当前 VC 上方,这就是导致警告/错误的原因。 当 didDismiss 被调用时,动作视图已经被关闭,所以完全没有问题:))

      【讨论】:

      • 这与@Kjuly 的答案相同。当我问/回答问题时,系统在didDismissWithButtonIndex: 上显示相同的警报。
      • 对不起。那个时候我没有看到那个答案:)
      【解决方案6】:

      我也有同样的问题。我在我的 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];
      

      【讨论】:

      • 请不要发布相同的问题作为答案。你可以再问一个问题。
      【解决方案7】:

      试试

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

          【解决方案9】:

          我用以下代码在 Swift 3 中修复了它

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

          【讨论】:

            猜你喜欢
            • 2016-02-03
            • 2020-06-25
            • 1970-01-01
            • 2013-10-26
            • 1970-01-01
            • 2011-01-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多