Matt Pfefferle
Matt Pfefferle

Reputation: 209

-didSelectRowAtIndexPath: not being called

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?

Upvotes: 308

Views: 226990

Answers (30)

Mithra Singam
Mithra Singam

Reputation: 2091

Check if your viewController has following method:

- (BOOL) tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
    return NO;
}

if you return "NO" didSelectRow won't be called

Upvotes: 5

w0mbat
w0mbat

Reputation: 2459

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."

Upvotes: 0

Denis Kutlubaev
Denis Kutlubaev

Reputation: 16204

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

Upvotes: 0

Serg Smyk
Serg Smyk

Reputation: 663

tableView?.allowsSelection = true

It's False by default in Xcode 11.7

Upvotes: 3

Dennis Krut
Dennis Krut

Reputation: 423

Another thing that might lead to the issue is not selected selection kind:

UITableView selection kind

Should be Single Selection for normal selection, should not be No Selection.

To do this programmatically, do:

tableView.allowsSelection = YES

Upvotes: 523

Prasad.Jakka
Prasad.Jakka

Reputation: 159

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.

Upvotes: 6

ATIQ UR REHMAN
ATIQ UR REHMAN

Reputation: 448

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

Upvotes: 0

Sasi
Sasi

Reputation: 1897

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!

Upvotes: 1

Prasanna Ramaswamy
Prasanna Ramaswamy

Reputation: 231

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) {

Upvotes: 0

Naveed Ahmad
Naveed Ahmad

Reputation: 6747

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

Upvotes: 14

Diego Maye
Diego Maye

Reputation: 327

Take care about the UITableView properties in the storyboard, what happened in my case was that I had the combox in the storyboard selected as "Selection: Single Selection", that does not allow the method didSelectRowAtIndexPath run.

Upvotes: 4

Hot'n'Young
Hot'n'Young

Reputation: 491

I can't comment, write here. In my case didSelectRow worked, but not didDeselectRow. I set delegate and dataSource for tableView and this solved my case.

Upvotes: 0

Mark Bridges
Mark Bridges

Reputation: 8458

I've just had this issue, however it didn't occur straight away; after selecting a few cells they would stop calling didSelectItemAtIndexPath. I realised that the problem was the collection view had allowsMultipleSelection set to TRUE. Because cells were never getting deselected this stopped future calls from calling didSelectItemAtIndexPath.

Upvotes: 1

Bartłomiej Semańczyk
Bartłomiej Semańczyk

Reputation: 61880

If the problem arise with UITapGestureRecognizer you can fix this:

  • in Storyboard:

enter image description here

in code with Objective-C:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)]; 
[self.view addGestureRecognizer:tap];

[tap setCancelsTouchesInView:NO];

in code with Swift:

let tap = UITapGestureRecognizer(target: self, action:Selector("dismissKeyboard"))
view.addGestureRecognizer(tap)

tap.cancelsTouchesInView = false

Upvotes: 95

SleepsOnNewspapers
SleepsOnNewspapers

Reputation: 3373

Make sure you implemented tableView:didSelectRowAtIndexPath and not tableView:didDeSelectRowAtIndexPath

This is gotten me on more than a few occasions !!

Upvotes: 7

Mohsin Qureshi
Mohsin Qureshi

Reputation: 1213

YOU MUST select these options

enter image description here

but if you want to make UITableViewnot highlighted on clicking then you should make changes in UITableViewCell properties.

Choose None option for Selection just like below

enter image description here

Upvotes: 24

Dilapidus
Dilapidus

Reputation: 425

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"

Upvotes: 0

Paul.V
Paul.V

Reputation: 416

in mine case i did a small mistake is I assigned:

tableView.isUserInteractionEnabled = false

it should be:

tableView.isUserInteractionEnabled = true

Upvotes: 0

Vinu David Jose
Vinu David Jose

Reputation: 2648

If you added a gestureRecognizer on top of the UITableView, didSelectRowAtIndexPath will not get called.

So you need to use gestureRecognizer delegate method to avoid touch in particular view.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isDescendantOfView:YourTable]) {
        return NO;
    }
    return YES;
}

Upvotes: 40

Supertecnoboff
Supertecnoboff

Reputation: 6616

Make sure you call reloadData on the main thread. If you are calling that method from some kind of asynchronous method (eg: a network request of some sort), the table view may or may not respond properly (in some cases the app can even crash).

Use a main thread code block to perform the reloadData call, if the call is being made in some other method block (which you are unsure of):

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    [tableView reloadData];
}];

Upvotes: 0

Lucas van Dongen
Lucas van Dongen

Reputation: 9878

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 }
}

Upvotes: 0

HonkyHonk
HonkyHonk

Reputation: 86

In my case the solution was to change NO to YES in the below function.

iOS 9+

- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

Upvotes: 5

John Doe
John Doe

Reputation: 403

If the cell you are clicking is being highlighted but the function is still not being called, double check your function's signature. It should look like this:

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

Upvotes: 2

dip
dip

Reputation: 139

  1. Add @interface ExampleViewController () <UITableViewDelegate, UITableViewDataSource>

  2. Make delegation in the storyboard

enter image description here

  1. Add code

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
       NSString *cellText = cell.textLabel.text;
    }
    

Upvotes: 0

yvetterowe
yvetterowe

Reputation: 1279

If your table view is in editing mode (eg. [tableView setEditing:YES animated:NO];), you need to set tableView.allowsSelectionDuringEditing = YES;

Upvotes: 5

DustinB
DustinB

Reputation: 11284

There are some amazing clues and answers in this post (maybe one of the best discussions I've seen!) The clues in here helped me figure out what my issue was, but I still spent many hours drooling on my keyboard trying to discover the issue, which was similar to other posts. However, how I finally discovered it was a bit different, so I wanted to share in case others come across it too.

Turns out my issue was that, in code, a superclass was adding a full-screen "error view" that was not hidden, but transparent. However, because it was over the tableview and "user action" was set to YES, it was intercepting my touches on the tableview.

I diagnosed this using Xcode's cool "Debug View Hierarchy" button. Here is a screen shot with annotations that hopefully explain what I did and how I ultimately diagnosed the issue.

In code, I simply had to do:

errorMessageView.setUserInteractionEnabled = NO;
// or
errorMessageView.hidden = YES;

Debug View Hierarchy

Upvotes: 3

Old McStopher
Old McStopher

Reputation: 6359

All good answers, but there's one more to look out for...

(Particularly when creating a UITableView programmatically)

Make sure the tableView can respond to selection by setting [tableView setAllowsSelection:YES]; or removing any line that sets it to NO.

Upvotes: 151

0xKayvan
0xKayvan

Reputation: 376

In my case the problem was I had a UITableViewCell subclass and I'd implemented these two methods: touchesBegan:withEvent: & touchesEnded:withEvent to handle a fancy animation on touch. But I'd forgotten to add the [super touchesBegan:touches withEvent:event]; method ad [super touchesEnded:touches withEvent:event]; to also inform the parent of cell of the touch.

So changing the code to following solved my problem:

-(void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{
    [super touchesBegan:touches withEvent:event];
    //blah blah blah
}

-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    //rest of the code
}

Upvotes: 4

MB_iOSDeveloper
MB_iOSDeveloper

Reputation: 4208

For Xcode 6.4, Swift 1.2 . The selection "tag" had been changed in IB. I don't know how and why. Setting it to "Single Selection" made my table view cells selectable again. enter image description here

Upvotes: 11

user486646
user486646

Reputation:

I just had this and as has happened to me in the past it didn't work because I didn't pay attention to the autocomplete when trying to add the method and I actually end up implementing tableView:didDeselectRowAtIndexPath: instead of tableView:didSelectRowAtIndexPath:.

Upvotes: 7

Related Questions