Search code examples
iosuinavigationcontrollerwkwebview

WKWebview allowsBackForwardNavigationGestures and UINavigationController interactivePopGestureRecognizer both enabled


My View Controller embedded inside a navigation controller holds a WKWebview on which I want to enable the following logic:

If a back item exists in the webview, making a left screen edge gesture should go back one page in the webview (normal behaviour of webview when allowsBackForwardNavigationGestures is set to yes). When there isnt any back item, it should pop one page in the navigation controller (interactivePopGestureRecognizer). I enabled both and I get random results, sometimes I go back one page in the webview and sometimes I go back to my home page in the navigation stack. I tried the following logic:

-(void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {

  if (webView.backForwardList.backItem) {
    MYappDelegate.mainNavigationController.interactivePopGestureRecognizer.enabled = NO;
    self.webView.allowsBackForwardNavigationGestures = YES;
  } else {
    MYappDelegate.mainNavigationController.interactivePopGestureRecognizer.enabled = YES;
    self.webView.allowsBackForwardNavigationGestures = NO;
  }
}

but it crashes when I swipe and I get "WKCompositingView unrecognized selector sent to instance."

Any ideas where I'm going wrong? Im guessing there is a conflict regarding which gesture takes priority but I cant figure out where to add this logic so both the webview and the navigation controller containing its view controller live peacefully.


Solution

  • I have a same issue. Please try the following way:

    Firstly, add a custom gesture to the WebView:

        let swipe = UISwipeGestureRecognizer(target: self, action: #selector(goBack))
        swipe.direction = UISwipeGestureRecognizerDirection.right
        swipe.delegate = self.navigationController
        webView.addGestureRecognizer(swipe)
    

    then, add a UIGestureDelegate method to deal with gesture simultaneously,

    extension UINavigationController: UIGestureRecognizerDelegate{
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return gestureRecognizer is UIScreenEdgePanGestureRecognizer
    }
    
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
    

    }

    But it has a minor defect that swiping effect differs from native one, which show new viewController when swiping without touch up.