357

I'm having an issue with UITableView's didSelectRowAtIndexPath.

My table is setup so that when I select row it initializes a new view controller and pushes it.

The first time I tap any row in the table, the method does not get called. Once I select another row, it begins to work as normal.

I have verified this by setting a breakpoint on didSelectRowAtIndexPath. When adding an NSLog to the method I see that when I select the second row that finally pushes the new view controller, I see two log statements appear in the console at the same time.

Any suggestions?

James Webster
  • 31,873
  • 11
  • 70
  • 114
Mark Adams
  • 30,776
  • 11
  • 77
  • 77

16 Answers16

1374

Any chance you accidentally typed didDeselectRowAtIndexPath?

Ole Begemann
  • 135,006
  • 31
  • 278
  • 256
  • IMO this answer doesn't explain why it only doesn't work on the first tap. It would be more correctly placed as an answer for this question: http://stackoverflow.com/questions/255927/didselectrowatindexpath-not-being-called – Jeehut Aug 19 '14 at 15:05
  • 18
    @Dschee it's not called on the first tap because you are not deselecting anything. Once you selected one row, when you try to select a second one, the first gets deselected. – The dude Sep 04 '14 at 13:30
  • Ah, dude, you're right of course. I was thinking of a scenario where I'd call `deselectRowAtIndexPath:` in `didSelectRowAtIndexPath:` which I often use. But of course that's not a general thing. Forgot that. ^^ – Jeehut Sep 05 '14 at 17:55
  • 2
    I am struggling with this one, although I *also* tried `didDeselectRowAtIndexPath`. I ended up using `didHighlightRowAtIndexPath` instead, and that responded on the first tap. – Jay Imerman Dec 25 '15 at 19:01
24

Also check the selection property of your table view in xib file. Use 'Single Selection' or 'Multiple Selection' as required.

includeMe
  • 2,672
  • 3
  • 25
  • 39
  • 2
    Ba ha ha ha! Wow I spent 4 hours trying to figure this out. @includeMe to the rescue (salute)! Thanks! –  Jul 26 '15 at 13:26
17

I experienced the following issue:

  • first tap in row -> no effect, no selection, never
  • second tap and following -> correct selection behavior, always

In my case, my error was checking Show Selection on Touch in Interface Builder. You can uncheck it in IB here:

enter image description here

Hope that helps someone

sonxurxo
  • 5,648
  • 2
  • 23
  • 33
13

Check If you have set any Gesture recognisers in your class. Removing gesture worked for me.

YSR fan
  • 705
  • 6
  • 11
  • I have both; Gesture recognizer and didSelectRowAtIndexPath? However, always the gesture recognizer takes preference. Unable to get to the second one. Is there a way to handle both or do I have to get rid of gesture recognizer? Thanks! – Ron Oct 20 '16 at 18:51
  • this must be at top :) it cost me 1 hour after 7 years in iOS development. – Clown Mar 12 '20 at 12:10
  • It cost me a lot more than an hour... Agreed, it should be at top! Thank you @YSR fan – Don Miguel Sep 22 '20 at 11:37
7

I debated even posting this answer because I think the stars kind of aligned in order for this to manifest itself.

I am having a variation of this problem and have checked the other solutions. On my table view it isn't processing the very last row of my table on the first tap. It highlights it, but didSelectRowAtIndexPath isn't being called. All the other rows work fine. But if I turn the tableview bounce on then it seems to solve the problem (but then you have to deal with a tableview bounce).

Chase Roberts
  • 9,082
  • 13
  • 73
  • 131
  • Did you find the reason why this is happening? I have exactly the same issue. When I turn off table bouncing, then the first / last row in the table does not react on the first tap. I thought it's bug but it's over one year and it's still happening. – filip.karas Apr 04 '15 at 17:16
  • No. I just turned on the tableview bounce and left it at that. – Chase Roberts Apr 04 '15 at 17:21
  • I'm having this issue on an iPhone 5 only (iOS 10.3) - turning ON bounce on my tableview fixed it. Very odd! – Lee Probert Mar 12 '18 at 09:30
  • Due to a system bug/misfeature, buttons at the bottom of the screen don't fire correctly due to system GestureRecognizers that are installed over the buttons. Fix here: https://stackoverflow.com/questions/23046539/uibutton-fails-to-properly-register-touch-in-bottom-region-of-iphone-screen/23787144#23787144 – Womble Jun 22 '20 at 05:58
5

UITableViewCellSelectionStyleNone was set for the cell displaying that problem (ios9).

I have ended up calling

[tableView deselectRowAtIndexPath:indexPath animated:NO];

first thing in

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

which is not the same, but is good enough. makes me wonder what kind of table breakage ios10 brings.

Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66
  • This worked for me but I need a workaround for hiding the selection without making its style None. I did override `setSelected` but while the user is holding the cell, the selection appears which is not acceptable – MMujtabaRoohani Aug 08 '17 at 10:59
2

this issue happens also when you are working with gesture recogniser within a tableView in this case you don't need to remove them, you need only to make sure that your gesture property cancelsTouchesInView = false this is a boolean value affecting whether touches are delivered to a view when a gesture is recognised.

Ayoub Nouri
  • 201
  • 1
  • 7
  • I am using table view inside gesture. As per the animation requirements I have to do this. So I am also facing same issue. I have to tap twice to select row at very first time. It get resolved after using gesture.cancelsTouchesInView = false Thanks. – Dilip Jangid Dec 03 '20 at 18:08
1

SWIFT 2

Make sure you have this set to true:

self.tableView.allowsSelection = true

Put this above your right after your viewDidLoad() and before the super.viewDidLoad()

Lukesivi
  • 2,206
  • 4
  • 25
  • 43
1

SWIFT 3

If you are working with Swift 3 in a class which isn't a UITableViewController and you are using UITableViewDelegate, then you may need to use the method title:

@objc(tableView:didSelectRowAtIndexPath:) func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){...}

This worked for me, although I have just migrated my project to Swift 3. It's fairly new so this may be fixed later.

ZGski
  • 2,398
  • 1
  • 21
  • 34
Adam Smith
  • 189
  • 1
  • 3
1

SWIFT 3

None of the other answers worked in my case, what fixed it for me was:

tableView.delaysContentTouches = false

1

If you have set any UITapGestureRecognizer in your class, you can add this line in your didSelectRowAtIndexPath:

[tableView deselectRowAtIndexPath:indexPath animated:NO];

This worked for me.

garridozh
  • 11
  • 1
1

Swift 4.2

Disabling "Delay Touch Down" in the attributes inspector solved the issue.
After that the clicks are smooth and didSelectRowAt fires immediately.

XCode attributes inspector

Aviv Mor
  • 469
  • 6
  • 6
0

didSelectRowAt function was not called in my app in first or second tap... I was trying to solve the problem could not find any solution. But suddenly I was recognise, I was using view.animation color change... Delegate method was not called while animation persist

Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
Ucdemir
  • 2,852
  • 2
  • 26
  • 44
0

In my case I had a UITableView section header with a gesture recognizer. When the header is tapped, it should insert few rows into that section and animate the insertion (like expand/collapse section). First time when expanded and tapped, the didSelectRow delegate method was not fired. For further taps and expand/collapse actions, it was working as expected.

Per answer by @Ayoub Nouri I set cancelsTouchesInView to false, and this resolved the issue. tapGestureRecognizer?.cancelsTouchesInView = false

Kabeer
  • 84
  • 5
0

What worked for me was to start typing "didSelect..." and then let autocorrect fill in the rest. Apparently some detail of my syntax was wonky. As others have said, Use the IDE!!

0

I had the same issue on my tableView(swift 4.2), it could be fixed with allowsMultipleSelection property on tableView.

If allowsMultipleSelection is set to true the table view selection mechanism will change in a way that by selecting each cell the tableView didSelectRowAtIndexPath: is called for the first time and by selecting the same cell for the second time the tableView didDeselectRowAtIndexPath: is called.

It means that if the number of times a cell tapped are odd (1, 3, 5, ...) then always tableView didSelectRowAtIndexPath: will be called and if the number of times a cell tapped are even (2, 4, 6, ...) then always tableView didDeselectRowAtIndexPath: will be called.

This makes tableView didSelectRowAtIndexPath: function to be called on the third selection for the same cell and so the result is double tap for calling didSelectRowAtIndexPath:!!!

If you want the tableView didSelectRowAtIndexPath: to be called on each selection for a cell then the tableView multiple selection has to be set false, tableView.allowsMultipleSelection = false.

By doing this, every time the cell is tapped tableView didSelectRowAtIndexPath: will be called on table view and by selecting another cell tableView didDeselectRowAtIndexPath: will be called for the cell was selected before and then the tableView didSelectRowAtIndexPath: will be called for the newly selected cell.

    class TableViewController: UITableViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.allowsMultipleSelection = false
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("This will be called for each cell tap")
    }