UIDocumentPickerViewController dismisses parent vi

2020-04-17 07:00发布

I have a WKWebView in a view controller. When an user clicks on "Upload File" button (which is on the webpage shown), UIDocumentPickerViewController pops up. This is expected and totally neccessary but:

Whenever the user clicks on any button ("Upload Photo or Video", "Cancel"), the UIDocumentPickerViewController dismisses itself AND the parent view controller that it's in.

I have added a symbolic breakpoint for [UIViewController dismissViewControllerAnimated:completion:] and indeed saw that -dismissViewController... is called twice. After the first time it dismisses UIDocumentPickerViewController, after the second one – my parent view controller.

By the way, on the iPad there is no problem, probably because UIDocumentPickerViewController is presented as a popover.

Why is this happening and what should I do?

Thanks!

4条回答
来,给爷笑一个
2楼-- · 2020-04-17 07:28

I faced the same problem and finally managed to find a workaround.

In my view controller I override dismiss method to delete managed object if save button wasn't hit and that worked perfectly with UIImagePickerController.

As of my application uses UIDocumentPickerViewController, my managed object was deleted each time the documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) was called because this causes a presentingViewController.dismiss.

So my solution is to check from the presentingViewController if the presentedViewController is nilor not to know if dismiss method was called by UIDocumentPickerViewController or not.

So here is my overriden dismiss method from my view controller.

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

Hope it helps you.

查看更多
一夜七次
3楼-- · 2020-04-17 07:35

Try this(working):

navigationController?.dismiss(animated: true, completion: nil)
查看更多
做个烂人
4楼-- · 2020-04-17 07:39

Alright, I think I've found a way to fix this. WebKit is open source, and you can see the offending class is WKFileUploadPanel, specifically the _dismissDisplayAnimated: method is called too aggressively inadvertently triggering dismissal of your view controller. In order to avoid this you need to block calls to -dismissViewControllerAnimated:completion: that come in from WKFileUploadPanel, which you can do by looking up the stack. Here's an implementation that resolves this.

The solution mentioned above doesn't work because it relies on looking at the call stack symbols for a particular class which is obfuscated when running on a real device. Here's a different approach I took to resolve this:

  1. Add a weak UIDocumentMenuViewController property to your modal view controller class.
  2. Override -presentViewController:animated:completion: in your modal class to check and see if the view controller being presented is a UIDocumentMenuViewController, if so set it as the value for your weak property from step 1.
  3. Override -dismissViewControllerAnimated:completion: to check if your weak property is nil yet, if it is not nil and your modal's presentedViewController is nil then it means that WebKit is trying to dismiss your modal when it shouldn't be. You can avoid calling super in that case, and continue calling it otherwise.

You can also swizzle WKFileUploadPanel's _dismissDisplayAnimated: method to be more careful about your own view controllers, but that comes with a significant amount of risk.

查看更多
5楼-- · 2020-04-17 07:46

I have faced the same issue , This happens while using document picker and occurs in iOS versions below 11.4 . Use the below code where ever you are using document picker. From what I have read from different forums there is an issue with document picker and it has been fixed in later versions of iOS .

Declare a weak property of document picker .

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

Then implement the view controller delegate methods :

- (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];
    }
}
查看更多
登录 后发表回答