44

I am attaching a UISwipeGestureRecognizer to a UITableViewCell in the cellForRowAtIndexPath: method like so:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(didSwipe:)];
        gesture.direction = UISwipeGestureRecognizerDirectionRight;
        [cell.contentView addGestureRecognizer:gesture];
        [gesture release];
    }
    return cell;
}

However, the didSwipe method is always getting called twice on successful swipe. I initially thought this was because the gesture starts and ends, but if I log out the gestureRecognizer itself, they are both in the "Ended" state:

-(void)didSwipe:(UIGestureRecognizer *)gestureRecognizer {

    NSLog(@"did swipe called %@", gestureRecognizer);
}

Console:

2011-01-05 12:57:43.478 App[20752:207] did swipe called <UISwipeGestureRecognizer: 0x5982fa0; state = Ended; view = <UITableViewCellContentView 0x5982c30>; target= <(action=didSwipe:, target=<RootViewController 0x5e3e080>)>; direction = right>
2011-01-05 12:57:43.480 App[20752:207] did swipe called <UISwipeGestureRecognizer: 0x5982fa0; state = Ended; view = <UITableViewCellContentView 0x5982c30>; target= <(action=didSwipe:, target=<RootViewController 0x5e3e080>)>; direction = right>

I really really don't know why. I tried obviously checking for the Ended state, but that is no help as they both come in as "Ended" anyway... Any ideas?

KlimczakM
  • 12,576
  • 11
  • 64
  • 83
mootymoots
  • 4,545
  • 9
  • 46
  • 74

4 Answers4

109

Instead of adding the gesture recognizer to the cell directly, you can add it to the tableview in viewDidLoad.

In the didSwipe-Method you can determine the affected IndexPath and cell as follows:

-(void)didSwipe:(UIGestureRecognizer *)gestureRecognizer {

  if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        CGPoint swipeLocation = [gestureRecognizer locationInView:self.tableView];
        NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:swipeLocation];
        UITableViewCell* swipedCell = [self.tableView cellForRowAtIndexPath:swipedIndexPath];
        // ...
  }
}
Felix
  • 35,354
  • 13
  • 96
  • 143
  • Thanks! That stopped it from firing twice! :) – mootymoots Jan 05 '11 at 17:55
  • Thanks, this helped, but I'm seeing something weird - after swiping I need to press twice if I want to select the row. The first time does nothing, and the second calls didSelectRow... Anybody seen this? – Oded Ben Dov Feb 27 '13 at 09:34
  • 1
    @OdedBenDov I believe it is caused by gesture recogniser,I had the strange behaviour for table view cell selection when I added tap gesture recogniser and forgot to remove in did end editing method of text field(sub view of table view cell),may be this can act as a clue to solve your issue,more details [here](http://stackoverflow.com/questions/9939509/strange-behavior-did-select-row-touch-not-responding-for-uitableviewcell) – Eshwar Chaitanya Aug 28 '13 at 10:26
  • You should probably check to see if swipedIndexPath is nil before calling cellForRowAtIndexPath. In my case, I was typing the third (non-existent) cell and it was returning a index path of nil, which then yielded an actual UITableViewCell (in that last line). – rrbrambley Oct 24 '13 at 02:15
0

I had this same problem and solved it by ticking "Scrolling Enabled" in the table view attributes.

My table view doesn't need scrolling, so it doesn't affect the app in any other way, except now I don't get the first unresponsive tap after a swipe gesture.

0

It will work with app delegate

- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{

// code

}
beryllium
  • 29,669
  • 15
  • 106
  • 125
Kumaresan P
  • 119
  • 2
  • 8
-1

Adding gesture in AwakeFromNib method works with no problems.

class TestCell: UITableViewCell {

    override func awakeFromNib() {
        super.awakeFromNib()

        let panGesture = UIPanGestureRecognizer(target: self,
                                            action: #selector(gestureAction))
        addGestureRecognizer(panGesture)
    }

    @objc func gestureAction() {
        print("gesture action")
    }
}
LembergSun
  • 641
  • 7
  • 14