Reputation: 209
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
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
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
Reputation: 16204
I had this issue, when the class name
of my TableViewController
had been set incorrectly in the Interface Builder
.
Upvotes: 0
Reputation: 663
tableView?.allowsSelection = true
It's False by default in Xcode 11.7
Upvotes: 3
Reputation: 423
Another thing that might lead to the issue is not selected selection kind:
Should be Single Selection
for normal selection, should not be No Selection
.
To do this programmatically, do:
tableView.allowsSelection = YES
Upvotes: 523
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
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
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
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
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
Upvotes: 14
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
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
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
Reputation: 61880
If the problem arise with UITapGestureRecognizer
you can fix this:
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
Reputation: 3373
Make sure you implemented tableView:didSelectRowAtIndexPath
and not tableView:didDeSelectRowAtIndexPath
This is gotten me on more than a few occasions !!
Upvotes: 7
Reputation: 1213
YOU MUST select these options
but if you want to make UITableView
not highlighted on clicking then you should make changes in UITableViewCell
properties.
Choose None option for Selection just like below
Upvotes: 24
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
Reputation: 416
in mine case i did a small mistake is I assigned:
tableView.isUserInteractionEnabled = false
it should be:
tableView.isUserInteractionEnabled = true
Upvotes: 0
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
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
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
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
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
Reputation: 139
Add @interface ExampleViewController () <UITableViewDelegate, UITableViewDataSource>
Make delegation in the storyboard
Add code
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
}
Upvotes: 0
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
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;
Upvotes: 3
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
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
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.
Upvotes: 11
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