【问题标题】:UIDocumentPickerViewController dismisses parent view controllerUIDocumentPickerViewController 关闭父视图控制器
【发布时间】:2016-12-11 11:57:33
【问题描述】:

我在视图控制器中有一个WKWebView。当用户点击“上传文件”按钮(在所示网页上)时,UIDocumentPickerViewController 会弹出。这是意料之中的,也是完全必要的,但是:

每当用户点击任何按钮(“上传照片或视频”、“取消”)时,UIDocumentPickerViewController 都会关闭自身及其所在的父视图控制器。

我为[UIViewController dismissViewControllerAnimated:completion:] 添加了一个符号断点,并且确实看到-dismissViewController... 被调用了两次。在第一次之后它会关闭 UIDocumentPickerViewController,在第二次之后 - 我的父视图控制器。

顺便说一句,在 iPad 上没有问题,可能是因为UIDocumentPickerViewController 是作为弹出框呈现的。

为什么会发生这种情况,我该怎么办?

谢谢!

【问题讨论】:

  • 我也看到了,你解决了吗?
  • 好的,我什至能够在一个非常简单的示例项目中重现这一点。我为此提交了一个 ID 为 29853806 的雷达,包括 this sample projectthis video demo of the bug
  • 嗯,我遇到了相反的问题:当我在弹出框外点击时,presentingViewController 被关闭。 ??????

标签: xcode wkwebview uidocumentpickervc


【解决方案1】:

好吧,我想我找到了解决这个问题的方法。 WebKit 是开源的,你可以看到有问题的类是WKFileUploadPanel,特别是_dismissDisplayAnimated: method 被过于激进地调用,无意中触发了视图控制器的关闭。为了避免这种情况,您需要阻止来自WKFileUploadPanel 的对-dismissViewControllerAnimated:completion: 的调用,您可以通过查找堆栈来做到这一点。这是解决此问题的实现。

上面提到的解决方案不起作用,因为它依赖于查看在真实设备上运行时被混淆的特定类的调用堆栈符号。这是我解决此问题的另一种方法:

  1. weak UIDocumentMenuViewController 属性添加到您的模态视图控制器类。
  2. 在模态类中覆盖 -presentViewController:animated:completion: 以检查并查看呈现的视图控制器是否为 UIDocumentMenuViewController,如果是,请将其设置为步骤 1 中的弱属性的值。
  3. 覆盖-dismissViewControllerAnimated:completion: 以检查您的弱属性是否为nil,如果它不是nil 并且您的模态的presentedViewControllernil,那么这意味着WebKit 正试图在它应该关闭您的模态时不是。在这种情况下,您可以避免调用 super,否则请继续调用。

您还可以调配WKFileUploadPanel_dismissDisplayAnimated: method 以更加小心自己的视图控制器,但这会带来很大的风险。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,最后设法找到了解决方法。

    在我的视图控制器中,如果没有点击保存按钮,我会覆盖 dismiss 删除托管对象的方法,并且与 UIImagePickerController 完美配合。

    由于我的应用程序使用UIDocumentPickerViewController,每次调用documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) 时都会删除我的托管对象,因为这会导致presentingViewController.dismiss

    所以我的解决方案是从presentingViewController 检查presentedViewController 是否为nil 或不知道dismiss 方法是否被UIDocumentPickerViewController 调用。

    所以这是我的视图控制器中覆盖的 dismiss 方法。

    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
        if self.presentedViewController == nil {
            // dismissed by the user
            myDocument.delete()
        } else {
            // dismissed by the UIDocumentPickerViewController
            // do nothing
        }
        super.dismiss(animated: flag, completion: completion)
    }
    

    希望对你有所帮助。

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,这发生在使用文档选择器时,并且发生在低于 11.4 的 iOS 版本中。在您使用文档选择器的任何地方使用以下代码。从我在不同论坛上看到的内容来看,文档选择器存在问题,该问题已在更高版本的 iOS 中得到修复。

      声明文档选择器的弱属性。

      @property (weak, nonatomic) UIDocumentPickerViewController *_Nullable docPicker;
      

      然后实现视图控制器委托方法:

      - (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion
      {
          if ([viewControllerToPresent isKindOfClass:[UIDocumentPickerViewController class]])
          {
              _docPicker = (UIDocumentPickerViewController*)viewControllerToPresent;
          }
      
          [super presentViewController:viewControllerToPresent animated:flag completion:completion];
      }
      
      - (void)dismissViewControllerAnimated:(BOOL)flag
                                 completion:(void (^)(void))completion
      {
          if (_docPicker != nil && self.presentedViewController == nil)
          {
      
          }
          else
          {
              [super dismissViewControllerAnimated:flag completion:completion];
          }
      }
      

      【讨论】:

        【解决方案4】:

        试试这个(工作):

        navigationController?.dismiss(animated: true, completion: nil)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-05-19
          • 1970-01-01
          • 2012-07-27
          • 2017-01-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多