MortimerGoro / MGSwipeTableCell

An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.
MIT License
6.96k stars 1.08k forks source link

Conflict with iOS standard "swipe to go back" #54

Closed MortimerGoro closed 8 years ago

MortimerGoro commented 9 years ago

Info received by mail:

Basically, it seems as though the MGSTC panGesture and the iOS standard "swipe to go back" gesture are stealing one anthers touches. Strangely, it seems like whichever is engaged first disables the other. i.e. Swipe a cell and the swipe-back gesture will never get called, it will only swipe other cells. But, if you engage the swipe-back gesture first, only part-ways and return into the view cell will no longer swipe!

At first I thought the solution would be to modify the _swipeView bounds so that the MGSTC panGesture isn't called if it initiate within the first x points (sy, 5) of the left screen edge. For some reason I can't get this to work properly and it adds strange behaviour (cells will only swipe once and then never again? weird).

Anyway, it's an unlikely situation for any of my users to find them in, but something I thought I'd bring to your attention. Any ideas?

mergesort commented 9 years ago

@MortimerGoro This is actually a pretty common use case, and was an issue for my users. I had this working with version 1.1.1, and it was a really nice effect by adding this to MGSwipeTableCell.m.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return [otherGestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]];
}

I'm trying to go through what's changed, and can't seem to be able to fix it. Now when I add that, the same issue continues, and also now the table view continues to scroll while you're opening the cell.

Let me know if this helps, I'd love to figure this out and be able to upgrade to 1.3.5.

MortimerGoro commented 9 years ago

hi Joe, I can't reproduce the issue. I tried the Swipe to go back (pushing a viewController in MGSwipeDemo and MailAppDemo) and I didn't find the conflict: Swipe to go back gesture and cell swipes are compatible. It works even without adding your code. Any ideas about how to reproduce the issue?

mergesort commented 9 years ago

@MortimerGoro It looks like you're right, there must be something conflicting with my code, because I can't recreate it in the demos, even after modifying it. I'm just using a regular UIViewController with a UITableView in my app, but will try and see if I can debug what circumstances are causing it to not work with 1.3.5.

Cs55Dev commented 9 years ago

Original submitter here.

Looking back through it seems like the issue is connected to my subclassing the cell and setting the layoutMargins to UIEdgeInsetsZero. I haven't had time to test extensively, but preventing _panRecognizer from receiving touches along the left edge seems to be working. Obviously you can set the value to whatever, but 10 points seems to be enough that the gestures no longer conflict.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
   shouldReceiveTouch:(UITouch *)touch;
{
    CGPoint touchLocation = [touch locationInView:touch.window];
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && touchLocation.x < 10) {
        return NO;
    } else {
        return  YES;
    }
}

I've added this to MGSwipeTableCell.m of the latest commit and everything seems to be working correctly.

mergesort commented 9 years ago

@Cs55Dev That makes sense, I was setting my layoutMargins to UIEdgeInsetsZero as well. Thanks for the fix!

sameera26 commented 9 years ago

I tried to implement native edge swiping feature. My problem is when i swipe left edge in the Tableview it is getting stuck. I can't scroll tableview after edge swiping. Please help me!

Cs55Dev commented 9 years ago

@sameera26

How did you implement edge swiping? With my code above?

If you put that code in your tableview you might be disabling touches for the pangesturerecognizer the tableview uses to scroll. You should put it in MGSwipeTableCell.m.

You could try replacing the if statement with: if (gestureRecognizer == _panRecognizer && touchLocation.x < 10) Haven't tested, but that ought to work.

sameera26 commented 9 years ago

Thanks for the quick response I implemented edge swiping in my detail view controller. But when the user swipe left edge to right in Tableview its getting stuck.

Cs55Dev commented 9 years ago

Hey there,

I'm having some trouble following exactly how you have your code set up. Could you post some code?

As I said, the BOOL method I posted should be in your MGSwipeTableCell implementation file. If you have it elsewhere you are going to run into conflicts with other pan gestures.

Seeing some code will help. Thanks! Mike

Sent from my iPhone

On Mar 26, 2015, at 7:28 AM, sameera26 notifications@github.com wrote:

Thanks for the quick response I implemented edge swiping in my detail view controller. But user swipe left edge to right in Tableview its getting stuck.

— Reply to this email directly or view it on GitHub.

sameera26 commented 9 years ago

How can I access touchLocation.x within the (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer method?

Thanks.

Cs55Dev commented 9 years ago

In the .h file add:

@property (nonatomic, assign) CGPoint touchLocation;

Then in the implementation file add the following method:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    _touchLocation = [touch locationInView:self.window];
}

You can then call _touchLocation.x in your method. But I caution you, if your plan is to use the x to prevent the gestureRecognizer from beginning by returning NO i went down that route and got weird behaviour.

It's much simpler to just prevent the gestureRecognizer from receiving the touch to begin with using the code I posted originally.

tobihagemann commented 9 years ago

I'm also having this issue, and afaik I'm not setting layoutMargins to UIEdgeInsetsZero. Or is this default? Either way, will this be fixed in a future release or do I also have to fix it myself?

sameera26 commented 9 years ago

I could fix this issue with using the code @Cs55Dev posted originally in this thread. And also I had to add below code in my tableview class.

override func viewWillDisappear(animated: Bool) {

        if(self.navigationController?.respondsToSelector("interactivePopGestureRecognizer") != nil) {
            self.navigationController?.interactivePopGestureRecognizer.enabled = true;
            self.navigationController?.interactivePopGestureRecognizer.delegate = nil
        }
}
override func viewDidAppear(animated: Bool) {
        if(self.navigationController?.respondsToSelector("interactivePopGestureRecognizer") != nil) {
            self.navigationController?.interactivePopGestureRecognizer.enabled = false;
                self.navigationController?.interactivePopGestureRecognizer.delegate = self
        }
}

Cheers!

MortimerGoro commented 9 years ago

I have added the following delegate method in 1.5.1:

-(BOOL) swipeTableCell:(MGSwipeTableCell*) cell canSwipe:(MGSwipeDirection) direction fromPoint:(CGPoint) point;

Now you can return false if point.x is too close to the edge

tobihagemann commented 9 years ago

Thanks for the addition! I'm just not sure if this is the right way to go. It seems far easier to subclass MGSwipeTableCell and just override the gestureRecognizer:shouldReceiveTouch: method as described above. Otherwise I'd have to add the same code in every view controller that conforms to MGSwipeTableCellDelegate.

But I guess that's okay to have it anyway, it probably depends on the use case.

mergesort commented 9 years ago

I would vote to keep this addition because I'd rather structure my code via composition and delegation rather than a subclass hierarchy. It also allows someone to set different x values, which is good because I actually don't have the same x values everywhere. With this solution in place you can still subclass if you do so choose to though.