UIDocumentPickerViewController dismisses parent view controller

℡╲_俬逩灬. 提交于 2019-12-02 02:22:18

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.

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.

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

Try this(working):

navigationController?.dismiss(animated: true, completion: nil)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!