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?
This question is related to
ios
uitableview
cocoa-touch
didselectrowatindexpath
This was probably only in my case, but I had reloaded some files from a backup and things were not working, including this. After doing a full clean (Product > Clean or Shift + Command + K) it worked. Probably something got messed up in a precompiled header. Chances are that's not the problem for you, but it's worth a shot.
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
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
}
Another possible cause seems to be that the UITableView
is embed in a UIScrollView
. I had this problem today because I inadvertently had a scroll view instead of a normal view as the root view of my controller.
If you read this, so still doesn't solve the problem.
I have custom cell, where checkbox "User Interaction Enabled" was disable. So, I Just switch on it. Good luck.
I have had the same problem. And it was hard to find. But somewhere in my code was this:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
It must be return indexPath
, else -tableView:didSelectRowAtIndexPath:
is not being called.
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"
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)
Another possibility is that a UITapGestureRecognizer could be eating the events, as was the case here: https://stackoverflow.com/a/9248827/214070
I didn't suspect this cause, because the table cells would still highlight blue as if the taps were getting through.
Remember to set the datasource and delegate in the viewDidLoad method as follows:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
My problem was none of the above. And so lame. But I thought I would list it here in case it helps someone.
I have a tableViewController
that is my "base" controller and then I create subclasses of this controller. I was writing all my code in the tableView:didSelectRowAtIndexPath
routine in the "base" class. Completely forgetting that by default this routine had also been created (albeit with no code that did anything) in all of my subclasses as well. So when I ran my app, it ran the subclass version of the code, did nothing, and made me sad. So of course, once I removed the routine from the subclasses, it used mt "base" class routine and I'm in business.
I know. Don't laugh. But maybe this will save someone the hour I lost...
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
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
In my case, just one cell was having this problem. The cell included UITextView outlet in readonly mode. Though it was readonly before tap. Upon tapping, keyboard rose. It turned out that it still needed to disable the interaction.
cell.content.scrollEnabled = NO;
cell.content.editable = NO;
cell.content.userInteractionEnabled = NO;
cell.content.delegate = nil;
[cell.content resignFirstResponder];
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.
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
.
I had this issue, when the class name
of my TableViewController
had been set incorrectly in the Interface Builder
.
Giving my 2 cents on this.
I had a Custom UITableViewCell and there was a button covering the whole cell, so when the touch happened, the button was selected and not the cell.
Either remove the button or in my case, I set User Interation Enable to false on the button, that way the cell was the one selected.
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;
}
Remember to set the datasource and delegate in the viewDidLoad method as follows:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
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.
Another possible cause seems to be that the UITableView
is embed in a UIScrollView
. I had this problem today because I inadvertently had a scroll view instead of a normal view as the root view of my controller.
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
}
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) {
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 }
}
Check if -heightForRowAtIndexPath doesnt return 0.
I have encountered two things in this situations.
You may have forgot to implement UITableViewDelegate protocol, or there's no delegation outlet between your class and your table view.
You might have a UIView inside your row that is a first responder and takes your clicks away. Say a UIButton or something similar.
I was having problem that control was not going in to didselect row after applying break point. problem was in view. I removed tab gesture from view. then its worked fine
Another crazy possibility: I was running my app on an iPhone 5S, and I used:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
as I always did in the past.
However, I didn't look closely enough at my compiler warnings... it said I should change that above line to:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
64-bit compatibility! shakes fist
Be on the lookout in case you start pulling your hair out.
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
If You have a custom cell, remember to set UserInteractionEnabled in the Xib (or via code) for the cell.
Another possibility is that a UITapGestureRecognizer could be eating the events, as was the case here: https://stackoverflow.com/a/9248827/214070
I didn't suspect this cause, because the table cells would still highlight blue as if the taps were getting through.
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.
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"
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.
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 :)
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
.
In case you have the same problem as me: Apparently, this method won't be called if your tableView is in edit mode. You have to set allowsSelectionDuringEditing to true.
Via this question: When editing, `UITableView` does not call didSelectRowAtIndexPath ??
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:
.
I iterated all previous answers but none of them helped me. After some trial and error I found a different solution. I had a UIImageView covering the whole cell (as a background). By default a UIImageView has user interaction disabled. By enabling the imageviews user interaction delegate method -didSelectRowAtIndexPath: was called again. eg.
cell.imgView.userInteractionEnabled = YES;
Giving my 2 cents on this.
I had a Custom UITableViewCell and there was a button covering the whole cell, so when the touch happened, the button was selected and not the cell.
Either remove the button or in my case, I set User Interation Enable to false on the button, that way the cell was the one selected.
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:
.
tableView?.allowsSelection = true
It's False by default in Xcode 11.7
I was having this problem intermittently. Sometimes touching a cell would cause it to be selected. Sometimes it would not receive the touch event.
I am using a features introduced in ios8 called self-sizing cells. I came across this blog post that points out that:
When the table view is first displayed, you may find some of the cells are not sized properly. But when you scroll the table view, the new cells are displayed with correct row height. To workaround this issue, you can force a reload after the view appears:
override func viewDidAppear(animated: Bool) {
tableView.reloadData()
}
This fixed the issue for me. Even though the table view was rendering correctly, touch handling (specifically hitTest of UITableView) seemed to be subject to the above-mentioned bug.
Make sure you implemented tableView:didSelectRowAtIndexPath
and not tableView:didDeSelectRowAtIndexPath
This is gotten me on more than a few occasions !!
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];
}];
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!
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
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)
Another mistake you could've done (as I did): if you set a segue at the cell, didSelectRowAtIndexPath
is not called. You should set your segues at the view controller instead.
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) {
I had a call to cell.userInteractionEnabled buried in some customized table code.
Stupid, yet aren't most bugs?
I had this problem myself. I had built the bones of the view in IB (just a View and a TableView) and the delegate wasn't set. I wired it up to File's Owner and it worked like a charm. ::save::
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 have had the same problem. And it was hard to find. But somewhere in my code was this:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
It must be return indexPath
, else -tableView:didSelectRowAtIndexPath:
is not being called.
If your table view is in editing mode (eg. [tableView setEditing:YES animated:NO];
), you need to set tableView.allowsSelectionDuringEditing = YES;
Ok, updating here as I just ran into this problem, and my issue was slightly different than found here.
I looked in IB and saw that my delegate WAS set, but it was set incorrectly to VIEW instead of File's Owner (right click on table view to see where delegate is pointing to).
Hope that helps someone
My problem was none of the above. And so lame. But I thought I would list it here in case it helps someone.
I have a tableViewController
that is my "base" controller and then I create subclasses of this controller. I was writing all my code in the tableView:didSelectRowAtIndexPath
routine in the "base" class. Completely forgetting that by default this routine had also been created (albeit with no code that did anything) in all of my subclasses as well. So when I ran my app, it ran the subclass version of the code, did nothing, and made me sad. So of course, once I removed the routine from the subclasses, it used mt "base" class routine and I'm in business.
I know. Don't laugh. But maybe this will save someone the hour I lost...
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
.
In my case, I dynamically calculate the height of the TableView
's SuperView
at load time. Due to a miscalculation, the TableView
was positioned outside of the SuperView
. The TableView
was drawn fine, however all interaction was disabled (and didSelectRowAtIndexPath
was never called). Very hard to detect, since there is no visual indication that the TableView
is not "accessible".
I had the same problem,
The reason was using of UITapGestureRecognizer
. I wanted the keyboard to dismiss when I tapped anywhere else. I realized that this overrides all tap actions, that is why, didSelectRowAtIndexPath
function did not called.
When I comment the rows related with UITapGestureRecognizer
, it works. Moreover you can check in the function of UITapGestureRecognizer selector
if the tapped is UITableViewCell
or not.
Another crazy possibility: I was running my app on an iPhone 5S, and I used:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
as I always did in the past.
However, I didn't look closely enough at my compiler warnings... it said I should change that above line to:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
64-bit compatibility! shakes fist
Be on the lookout in case you start pulling your hair out.
Just in case someone made the same stupid mistake as I did:
Check out if the method name of what you expect of being didSelect
may accidentally be gotten didDeselect
in some way. It took about two hours for me to find out ...
This was probably only in my case, but I had reloaded some files from a backup and things were not working, including this. After doing a full clean (Product > Clean or Shift + Command + K) it worked. Probably something got messed up in a precompiled header. Chances are that's not the problem for you, but it's worth a shot.
I had this issue, when the class name
of my TableViewController
had been set incorrectly in the Interface Builder
.
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;
}
tableView?.allowsSelection = true
It's False by default in Xcode 11.7
I have encountered two things in this situations.
You may have forgot to implement UITableViewDelegate protocol, or there's no delegation outlet between your class and your table view.
You might have a UIView inside your row that is a first responder and takes your clicks away. Say a UIButton or something similar.
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];
}];
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
.
I had this problem myself. I had built the bones of the view in IB (just a View and a TableView) and the delegate wasn't set. I wired it up to File's Owner and it worked like a charm. ::save::
I had a call to cell.userInteractionEnabled buried in some customized table code.
Stupid, yet aren't most bugs?
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 }
}
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.
If you read this, so still doesn't solve the problem.
I have custom cell, where checkbox "User Interaction Enabled" was disable. So, I Just switch on it. Good luck.
If your table view is in editing mode (eg. [tableView setEditing:YES animated:NO];
), you need to set tableView.allowsSelectionDuringEditing = YES;
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
I've ran into a problem where after months of not looking at my code I forgot that I implemented the following method due to some requirements which were not necessary
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
It should be returning YES for a row in order to make it selected.
I was having problem that control was not going in to didselect row after applying break point. problem was in view. I removed tab gesture from view. then its worked fine
In my case, just one cell was having this problem. The cell included UITextView outlet in readonly mode. Though it was readonly before tap. Upon tapping, keyboard rose. It turned out that it still needed to disable the interaction.
cell.content.scrollEnabled = NO;
cell.content.editable = NO;
cell.content.userInteractionEnabled = NO;
cell.content.delegate = nil;
[cell.content resignFirstResponder];
Check if -heightForRowAtIndexPath doesnt return 0.
I have encountered two things in this situations.
You may have forgot to implement UITableViewDelegate protocol, or there's no delegation outlet between your class and your table view.
You might have a UIView inside your row that is a first responder and takes your clicks away. Say a UIButton or something similar.
Just in case someone made the same stupid mistake as I did:
Check out if the method name of what you expect of being didSelect
may accidentally be gotten didDeselect
in some way. It took about two hours for me to find out ...
I was having this problem intermittently. Sometimes touching a cell would cause it to be selected. Sometimes it would not receive the touch event.
I am using a features introduced in ios8 called self-sizing cells. I came across this blog post that points out that:
When the table view is first displayed, you may find some of the cells are not sized properly. But when you scroll the table view, the new cells are displayed with correct row height. To workaround this issue, you can force a reload after the view appears:
override func viewDidAppear(animated: Bool) {
tableView.reloadData()
}
This fixed the issue for me. Even though the table view was rendering correctly, touch handling (specifically hitTest of UITableView) seemed to be subject to the above-mentioned bug.
If You have a custom cell, remember to set UserInteractionEnabled in the Xib (or via code) for the cell.
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;
}
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.
I had the same problem,
The reason was using of UITapGestureRecognizer
. I wanted the keyboard to dismiss when I tapped anywhere else. I realized that this overrides all tap actions, that is why, didSelectRowAtIndexPath
function did not called.
When I comment the rows related with UITapGestureRecognizer
, it works. Moreover you can check in the function of UITapGestureRecognizer selector
if the tapped is UITableViewCell
or not.
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 had put a UITapGestureRecognizer
on my table view to dismiss the keyboard which prevented didSelectRowAtIndexPath:
from being called. Hope it helps someone.
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;
}
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;
}
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
in mine case i did a small mistake is I assigned:
tableView.isUserInteractionEnabled = false
it should be:
tableView.isUserInteractionEnabled = true
I have encountered two things in this situations.
You may have forgot to implement UITableViewDelegate protocol, or there's no delegation outlet between your class and your table view.
You might have a UIView inside your row that is a first responder and takes your clicks away. Say a UIButton or something similar.
Make sure you implemented tableView:didSelectRowAtIndexPath
and not tableView:didDeSelectRowAtIndexPath
This is gotten me on more than a few occasions !!
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
Another mistake you could've done (as I did): if you set a segue at the cell, didSelectRowAtIndexPath
is not called. You should set your segues at the view controller instead.
I iterated all previous answers but none of them helped me. After some trial and error I found a different solution. I had a UIImageView covering the whole cell (as a background). By default a UIImageView has user interaction disabled. By enabling the imageviews user interaction delegate method -didSelectRowAtIndexPath: was called again. eg.
cell.imgView.userInteractionEnabled = YES;
None of these answers worked for me. After about an hour, I figured out something very insidious:
I have a table view inside a cell of another table view. I decided to make an enclosing view that contains the inner table view, among other things. I called this view contentView and hooked it up in the xib.
Turns out that UITableViewCell already has a contentView and does weird things with it. The issue resolved itself when I renamed the property to mainContentView and reconnected the view to this renamed property.
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;
I had put a UITapGestureRecognizer
on my table view to dismiss the keyboard which prevented didSelectRowAtIndexPath:
from being called. Hope it helps someone.
Ok, updating here as I just ran into this problem, and my issue was slightly different than found here.
I looked in IB and saw that my delegate WAS set, but it was set incorrectly to VIEW instead of File's Owner (right click on table view to see where delegate is pointing to).
Hope that helps someone
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;
}
In case you have the same problem as me: Apparently, this method won't be called if your tableView is in edit mode. You have to set allowsSelectionDuringEditing to true.
Via this question: When editing, `UITableView` does not call didSelectRowAtIndexPath ??
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 :)
in mine case i did a small mistake is I assigned:
tableView.isUserInteractionEnabled = false
it should be:
tableView.isUserInteractionEnabled = true
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've ran into a problem where after months of not looking at my code I forgot that I implemented the following method due to some requirements which were not necessary
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
It should be returning YES for a row in order to make it selected.
None of these answers worked for me. After about an hour, I figured out something very insidious:
I have a table view inside a cell of another table view. I decided to make an enclosing view that contains the inner table view, among other things. I called this view contentView and hooked it up in the xib.
Turns out that UITableViewCell already has a contentView and does weird things with it. The issue resolved itself when I renamed the property to mainContentView and reconnected the view to this renamed property.
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;
In my case, I dynamically calculate the height of the TableView
's SuperView
at load time. Due to a miscalculation, the TableView
was positioned outside of the SuperView
. The TableView
was drawn fine, however all interaction was disabled (and didSelectRowAtIndexPath
was never called). Very hard to detect, since there is no visual indication that the TableView
is not "accessible".
Source: Stackoverflow.com