Enricoza / EZCustomNavigation

Easy Custom Navigation Controller that allows popping view controllers with pan gesture from center too and UnPop them back in.
MIT License
23 stars 5 forks source link

Pan-To-Pop conflicts with `leadingSwipeActions` on UITableView cells #6

Open Enricoza opened 3 years ago

Enricoza commented 3 years ago

On a tableView with leadingSwipeActions the pan-to-pop gesture takes precedence over the _UISwipeActionPanGestureRecognizer of the tableView, making it impossible to show and activate those leading actions.

It should be allowed to, at least, disable the pan-to-pop entirely on some view controllers or, even better, it should be allowed to make it require the other gesture to fail and, therefore, take precedence.

ReDetection commented 3 years ago

I think it's worth to look into gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) and gestureRecognizer(_:shouldRequireFailureOf:) delegate methods. I was nearly able to achieve desired behavior, but seem to miss something since I didn't get it robust

ReDetection commented 3 years ago

OK I'm stuck again. There are two system recognizers we would be probably interested in:

You can see for the shitty workaround in my demo-delegate branch.

ReDetection commented 3 years ago

The best debug trick I know is to set a symbolic breakpoint on -[UIWindow sendEvent:] and add an automatic debugger command po [[[$arg3 allTouches] anyObject] gestureRecognizers] and enable automatic continue. This way you can observe all the recognizers and their states as they change

ReDetection commented 3 years ago

Ha, scroll view exposes it's pan gesture recognizer :) so the workaround just got a lot better. Please see the #8

Enricoza commented 3 years ago

Hi @ReDetection, it's needlessly to say how much I appreciate your work and tips. It really helps a lot, so thanks.

I had found the _UISwipeActionPanGestureRecognizer too, but since it's private I wouldn't want to hardcode its name.

Anyway thanks also for the PR, it's highly appreciated. Unfortunately I can't review it right now but I will look at it later today.

VasApps commented 3 years ago

I had this issue in my app as well and I managed to fix it by recursively searching for the tableView in the last viewController of the navigation stack. Once you find the tableView you can simply check for isEditing and then return. I attached the code below.

` private func handleGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer, forPop: Bool) {

    let viewControllers = visibleViewController?.navigationController?.viewControllers

    var isEditingTableView = false

    if viewControllers != nil {

        let lastVC = viewControllers![viewControllers!.count - 1]

        if let tableView = lastVC.view.recursiveSearch(type: UITableView.self) as? UITableView{

            isEditingTableView = tableView.isEditing

        }
    }

    if isEditingTableView {

        return
    }

    guard let gestureRecognizerView = gestureRecognizer.view,
        enableFollowingGesturesWhileAnimating || !coordinator.onGoingAnimation else {
        return
    }

    let percent = gestureRecognizer.translation(in: gestureRecognizerView).x / gestureRecognizerView.bounds.size.width
    onInteractiveGestureRecongnizerState(gestureRecognizer.state,
                                         percent: forPop ? percent : -percent,
                                         onShouldActivate: forPop ? self.onShouldPopViewController : self.onShouldUnpopViewController)

}`
Enricoza commented 3 years ago

Hi @VasApps! First and foremost, thank you for your input.

Unfortunately I think your issue is not the same we are talking about in this thread and your solution is, anyway, not really viable.

Here we are talking about a tableView that has the method leadingSwipeActionsConfigurationForRowAt implemented and returning some UIContextualAction for some row. In this case the left-to-right swipe conflicts with that swipe action that opens the left menu, so the leadingActions can never be triggered. This API is not triggered just when the tableView is in Editing mode, so your code would serve no purpose in this case.

That said, assuming there is another issue when a tableView is in editing mode, your solution would prevent whatever pop gesture (if there is any tableView in editing mode) while still capturing the gesture priority and therefore preventing whatever other left-to-right pan gesture that goes in conflict. This is not the intended behavior.

Even if it were, I don't think that looking for the tableView recursively would be something that can be part of this library.

If you feel like I miss interpreted something you just said, you can correct me and let me understand better. You can also open a new issue if this actually is an entirely new issue and doesn't regard leadingSwipeActionsConfigurationForRowAt and explain more precisely what is that you would like to happen versus what actually is happening.