Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long press leads to an error/warning when WKWebView tries to present a WKActionSheet

My view hierarchy looks like this:

  • (root) PRSBaseViewController - a UIViewController subclass - has child viewControllers
    • (presented) PRSModalWebViewController - a UINavigationController subclass
      • (pushed, animated:NO) PRSWebViewController - a UIViewController subclass - WKWebView is a subview.

When I try and long press on a link in the WebView I get the error:

Warning: Attempt to present <WKActionSheet: 0x127520d10> on <PRSBaseViewController: 0x1275117f0> whose view is not in the window hierarchy!

Instead of presenting the navigation using presentViewController:animated:completion and instead use the addChildViewController: dance to add it the view controller to the hierarchy. I get no errors, It's quite strange.

Does anyone know what could be causing the view hierarchy issues?

Update: I've made a Gist of all my classes

like image 816
Shawn Throop Avatar asked Jan 04 '15 16:01

Shawn Throop


2 Answers

I have come across a similar behavior - and have not figured out how or why this occurs either.

Here is my workaround. Since WKWebView is calling my RootViewController, I'm handling this by overriding RootViewController's presentViewController:animated:completion: - and if the RootViewController already has a presentedViewController, then it forwards the message to that controller. It seems to address the warning message, and gives me the long press menu when using WKWebView inside a modal view.

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {

    // Unsure why WKWebView calls this controller - instead of it's own parent controller
    if (self.presentedViewController) {
        [self.presentedViewController presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
        [super presentViewController:viewControllerToPresent animated:flag completion:completion];
    }
}

Or in swift:

override func presentViewController(viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?) {
    if presentedViewController != nil {
        // Unsure why WKWebView calls this controller - instead of it's own parent controller
        presentedViewController?.presentViewController(viewControllerToPresent, animated: flag, completion: completion)
    } else {
        super.presentViewController(viewControllerToPresent, animated: flag, completion: completion)
    }
}
like image 118
Todd Avatar answered Sep 20 '22 04:09

Todd


We've seen this issue in PSPDFKit as well and after investigating the UIKit assembly and WKWebView sources we found a workaround that is still horrible, but not invasive.

The main strategy is to be selective and apply a workaround just in time - then clean up again. You can read the source code here:

https://gist.github.com/steipete/b00fc02aa9f1c66c11d0f996b1ba1265

And please dupe rdar://26295020 so this will get hopefully fixed in time for iOS 10. (The bug exists since iOS 8 and was first reported on iOS 8b5.)

like image 30
steipete Avatar answered Sep 18 '22 04:09

steipete