Problems using UIPanGestureRecognizer in UITableViewCell

ios, objective-c, uigesturerecognizer, uitableview

Solution

If you don't want the cell's swipe gesture to happen simultaneously with the table view scroll gesture, then add a pan gesture to your cell and make it a delegate:

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(doPan:)];
pan.delegate = self;
[self addGestureRecognizer:pan];

And implement the following delegate method to only start if the pan is horizontal:

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    // note: we might be called from an internal UITableViewCell long press gesture

    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {

        UIPanGestureRecognizer *panGestureRecognizer = (UIPanGestureRecognizer*)gestureRecognizer;
        UIView *cell = [panGestureRecognizer view];
        CGPoint translation = [panGestureRecognizer translationInView:[cell superview]];

        // Check for horizontal gesture
        if (fabs(translation.x) > fabs(translation.y))
        {
            return YES;
        }

    }

    return NO;
}

Swift3 ..

override func awakeFromNib() {
    super.awakeFromNib()
    // do not use, say, layoutSubviews as layoutSubviews is called often
    let p = UIPanGestureRecognizer(target: self, action: #selector(yourPan))
    p.delegate = self
    contentView.addGestureRecognizer(p)
    }
}

override func gestureRecognizerShouldBegin(_ g: UIGestureRecognizer) -> Bool {
    if (g.isKind(of: UIPanGestureRecognizer.self)) {
        let t = (g as! UIPanGestureRecognizer).translation(in: contentView)
        let verticalness = abs(t.y)
        if (verticalness > 0) {
            print("ignore vertical motion in the pan ...")
            print("the event engine will >pass on the gesture< to the scroll view")
            return false
        }
    }
    return true
}

Problem

I'm trying to implement a UIPanGestureRecognizer in my UITableViewController to use for a swipe to delete animation. Similar to the swipe to delete used in the Clear app, where if you swipe a UITableViewCell in left or right the cell moves and gets deleted. I have tried implementing this in my UITableViewCell subclass but it never seems to receive the event. This is the code I put in my UITableViewCell subclass to try this functionality. In my init method ``` UIGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; recognizer.delegate = self; [self addGestureRecognizer:recognizer]; ``` and then the methods to handle it: ``` - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer { CGPoint translation = [gestureRecognizer translationInView:self.superview]; //might have to change view to tableView //check for the horizontal gesture if (fabsf(translation.x) > fabsf(translation.y)) { return YES; NSLog(@"Panning"); } return NO; } - (void)handlePan:(UIPanGestureRecognizer *)recognizer { if (recognizer.state == UIGestureRecognizerStateBegan) { //if the gesture has just started record the center location NSLog(@"handlePan"); _originalCenter = self.center; //Declared as a CGPoint at the top of my TableViewCell } if (recognizer.state == UIGestureRecognizerStateChanged) { //translate the center (aka translate from the center of the cell) CGPoint translation = [recognizer translationInView:self]; self.center = CGPointMake(_originalCenter.x + translation.x, _originalCenter.y); // determine whether the item has been dragged far enough to delete/complete } if (recognizer.state == UIGestureRecognizerStateEnded) { // the frame this cell would have had before being dragged CGRect originalFrame = CGRectMake(0, self.frame.origin.y, self.bounds.origin.x, self.bounds.size.height); [UIView animateWithDuration:0.2 animations:^{ self.frame = originalFrame;} ]; } } ``` The Cells don't move at all though. Not really sure what's going on here

Original source