UIDocumentPickerViewController关闭父视图控制器。

3
我有一个视图控制器中的WKWebView。当用户点击“上传文件”按钮(显示在网页上)时,UIDocumentPickerViewController弹出。这是预期和必要的,但是:
无论用户点击“上传照片或视频”、“取消”按钮中的任何一个,UIDocumentPickerViewController都会关闭自己和它所在的父视图控制器。
我已经添加了[UIViewController dismissViewControllerAnimated:completion:]的符号断点,并确实看到-dismissViewController...被调用了两次。第一次是将UIDocumentPickerViewController退出,第二次是退出我的父视图控制器。
顺便说一句,在iPad上没有问题,可能是因为UIDocumentPickerViewController作为弹出窗口呈现。
为什么会发生这种情况,我该怎么办?
谢谢!

我也看到了这个问题,你解决了吗? - Tim Johnsen
1
好的,我甚至能够在一个非常简单的示例项目中复现这个问题。我为此提出了编号为 #29853806 的雷达反馈,并附上了这个示例项目这个错误的视频演示 - Tim Johnsen
我有相反的问题:当我在弹出窗口外部点击时,presentingViewController 被解除了。 - bio
4个回答

2
好的,我想我找到了解决方法。WebKit是开源的,你可以看到问题所在的类是WKFileUploadPanel,具体来说,_dismissDisplayAnimated: 方法被过于激进地调用,意外触发了视图控制器的关闭。为了避免这种情况,你需要阻止来自WKFileUploadPanel-dismissViewControllerAnimated:completion:调用,这可以通过查找堆栈来实现。下面是一个解决方案的实现。
上述提到的解决方案不起作用,因为它依赖于查看特定类的调用堆栈符号,在真实设备上运行时会被混淆。以下是我采取的另一种方法来解决这个问题:
将以下文本从英语翻译成中文:
  1. 在模态视图控制器类中添加一个weak UIDocumentMenuViewController属性。
  2. 在你的模态类中覆盖-presentViewController:animated:completion:,检查并查看被呈现的视图控制器是否为UIDocumentMenuViewController,如果是,则将其设置为步骤1中弱属性的值。
  3. 覆盖-dismissViewControllerAnimated:completion:以检查您的弱属性是否仍为nil,如果不是nil且您的模态presentedViewControllernil,则意味着WebKit试图在不应该的情况下关闭您的模态。在这种情况下,您可以避免调用super,否则继续调用它。

您还可以交换WKFileUploadPanel_dismissDisplayAnimated:方法以更加小心地处理自己的视图控制器,但这会带来相当大的风险。


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)
}

希望能对您有所帮助。

1
我遇到了相同的问题,这是在使用文档选择器时发生的,并且发生在iOS 11.4以下的版本中。无论您在哪里使用文档选择器,请使用下面的代码。根据我从不同论坛上阅读到的内容,文档选择器存在问题,并且已经在后续的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];
    }
}

0
试试这个(可行):
navigationController?.dismiss(animated: true, completion: nil)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接