-didSelectRowAtIndexPath: not being called

Viewed 221842

I'm writing an iOS app with a table view inside a tab view. In my UITableViewController, I implemented -tableView:didSelectRowAtIndexPath:, but when I select a row at runtime, the method isn't being called. The table view is being populated though, so I know that other tableView methods in my controller are being called.

Does anyone have any ideas what I may have screwed up to make this happen?

60 Answers

It sounds like perhaps the class is not the UITableViewDelegate for that table view, though UITableViewController is supposed to set that automatically.

Any chance you reset the delegate to some other class?

I have encountered two things in this situations.

  1. You may have forgot to implement UITableViewDelegate protocol, or there's no delegation outlet between your class and your table view.

  2. You might have a UIView inside your row that is a first responder and takes your clicks away. Say a UIButton or something similar.

In my case, didSelctRowAtIndexPath not calling is due to that I have selected none in the Selection property of tableView, set to single selection solved my problem

enter image description here

Even though another answer has been accepted, I'll add one more possible problem and solution for people who observe this issue:

If you have automatic reference counting (ARC) turned on, you may find that even after assigning your controller as a delegate of the view, the view's messages to the controller are not being received because ARC is deleting the controller. Apparently the UITableView's delegate pointer does not count as a reference for the ARC, so if that is the only reference to it, the controller will be dealloc'd. You can verify whether or not this is happening by implementing the dealloc method on the controller and setting a breakpoint or NSLog call there.

The solution is to keep track of the controller with a strong reference somewhere else, until you are sure you won't need it anymore.

Please check for UITapGestureRecognizer. In my case tapgesture was added for the view where tableview got placed, which is eating the user interaction of UITableview like didselect. After disabling tapgesture for the view, didselect delegate was triggered.

I know is old and the problem was resolved, but a had similar problem, I thought that the problem was with my custom UITableViewCell, but the solution was completely different - I restart XCode :) and then works ok ! almost like Windows :)

tableView?.allowsSelection = true

It's False by default in Xcode 11.7

I have read all the answers and strongly agree with them. But it is entirely different in my case. I had new segue for my detailViewController linked directly to my tableCell in StoryBoard which caused this. So I had to remove that segue from my cell and linked it with the UITableViewController itself. Now by writing the following code it works,

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        // Do any operation
        performSegue(withIdentifier: "DetailSegue", sender: self)
    }

Hope this solution will help someone out there!

I'm not sure if anybody scrolls far enough to see this answer but since this is the most popular question about this subject and the answer wasn't there I'll add it:

As of Xcode 9 / Swift 4 all Objective-C methods should be marked @objc. The compiler does a reasonable job of recognizing where it should be applied however it doesn't figure out inheritance. For example:

class Delegate: NSObject, UITableViewDelegate {
}

class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}

This will not generate any warning, crashing or build error. However your line will not be called until you add @objc:

@objc class SuperDelegate: Delegate {
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { return indexPath }
}

I just found another way to not get your didSelect method called. At some point, prolly during some error in func declaration itself, XCode suggested I add @nonobjc to my method :

@nonobjc func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

This will continue to compile without complaint but you will never get called by the ui actions.

"That's my two cents and I'll be wanting my change back"

In my case, the problem was declaring the method as a private.

This didn't work:

private func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

This worked:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

you must check this selection must be single selection and editing must be no seleciton during edition and you change setting in uttableviewcell properties also you edit in table view cell style must be custom and identifier must be Rid and section is none

I had this issue, when the class name of my TableViewController had been set incorrectly in the Interface Builder.

A common error is to write code that calls selectRowAtIndexPath or deselectRowAtIndexPath and assume that the call will trigger a call to your delegate's didSelectRowAtIndexPath. It does not.

The documentation for selectRowAtIndexPath and deselectRowAtIndexPath clearly states:

"These methods will not call the delegate methods tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath:, nor will it send out a notification."

Related