16

My app uses a UITableView with a UINavigationController to show a more detailed view when a row of the table is tapped - the basic drill-down routine.

When I tap on a row, it is highlighted, but the delegate methods tableView:willSelectRowAtIndexPath: or tableView:didSelectRowAtIndexPath: are not called (verified using debugger).

Now here's the weird part:

  1. There are some other table views in the app (they don't drill down) and none of them exhibit the issue.

  2. If I tap the row rapidly and repeatedly, after many tries (10 - 20 is normal), tableView:willSelectRowAtIndexPath: and tableView:didSelectRowAtIndexPath: are called and processing continues normally.

  3. The problem occurs only on an (any, actually) iPad running iOS 6. It works fine with iPads running iOS 5, or with any iPhone running any iOS version, 6. It also works with the iPad simulator using iOS 5 or 6.

So it seems that something is receiving the tap before the delegate methods are called. But what?

I not using any UITapGestureRecognizer, so that is not the issue. I am not using multiple UITableViewControllers for the table, so this is also not the issue.

Community
  • 1
  • 1
Anton Meyer
  • 171
  • 1
  • 1
  • 5
  • 1
    Check these things: 1. Confirm the you are the delegate. 2. Does the cells contain any other view? Possibly a UIScrollView or any of it's descendants? 3. Are you running anything very demanding on the main thread? – ABeanSits Sep 26 '12 at 21:02
  • 1. Yes, I am definitely the delegate. 2. Some of the cells contain a UIImageView (with user interaction disabled), the rest contain just the usual UILabel. 3. No, the app is idling. – Anton Meyer Sep 26 '12 at 21:09
  • Have you done any kind of override of the main UIWindow? – Mike M Sep 26 '12 at 21:26
  • Have you set a window rootViewController correctly? iOS6 causes a few things to break if you haven't done this. – Roger Sep 26 '12 at 21:45
  • @Mike M I did not override the main UIWindow in any way. – Anton Meyer Sep 26 '12 at 22:49
  • @Roger The window rootViewController is a UITabBarController (I checked this in the AppDelegate in `application:didFinishLaunchingWithOptions:` by calling [_window rootViewController]). I'm not sure what you mean by "set a window rootViewController correctly"? – Anton Meyer Sep 26 '12 at 22:53
  • @StevenFisher There are two types of cells in the table, both are style 'basic' in IB. One contains only a UILabel (no details with these cells), the other contains a UIImage, UILabel, and a AcessoryDetailDisclosureButton. Both types do not get selected when tapped. – Anton Meyer Sep 27 '12 at 06:01
  • Hmmm this sounds like an adventure. :) Can you recreate this issue in a new project? – ABeanSits Sep 27 '12 at 12:18
  • I'm having the same problem and I changed the cells to have a blue selection color. You can see it in action. When you tap the cell, it will flash blue and then not actually call didSelectRowAtIndexPath. – Brandon O'Rourke Oct 08 '12 at 20:09

9 Answers9

11

I was having this issue with an app when running in iOS6. The tableView:didSelectRowAtIndexPath: method was never being triggered, even though it was working before updating to iOS6.

I finally figured it out by looking at the xib and the attribute inspector for the table. In the Table View section I had the Selection option set to No Selection and Show Selection on Touch was not selected.

Changing the Selection option to Single Selection actually got this working for me again and leaving the Show Selection on Touch unselected means that I don't see any flash or change of colour when the row is selected.

AidenMontgomery
  • 1,612
  • 1
  • 17
  • 24
  • I checked my storyboard file. The **Selection** is set to **Single Selection**. **Show Selection on Touch** does not seem to have any effect. – Anton Meyer Oct 28 '12 at 13:17
  • I am not using a storyboard, so maybe this is why it is different for me. Sorry I can't be more helpful. – AidenMontgomery Oct 29 '12 at 20:12
  • 1
    Yes, It's a correct answer on IOS 6 and 7, if you set table to no selection, "DidSelectRowAtIndexPath" will not be called. I have tested it and it works like that. – Adeel Pervaiz Jun 27 '14 at 10:16
8

I encountered a similar issue. iOS 6 appears to be much more sensitive to the slightest upward movement on a tap on a table view cell. It appears it is registering the slightest movement as a scroll request rather than a cell selection. My table view was set to scrollEnabled = NO because it is a table view with static selection values. The table view appears within a small area of a larger iPad view. If I carefully tap a cell and lift directly up, the cell is selected.

To resolve it, I changed scrollEnabled to YES and made sure the area dedicated to my tableView was larger than the actual area needed to show the table view, thus preventing it from scrolling. Not sure if this is is the cause of the issue you are experiencing, but hope it helps.

Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
Kynerd
  • 81
  • 1
  • Interesting. _scrollEnabled_ is _YES_ for the UITableView, because it can get larger than the screen, so that is not it. But your indication that iOS 6 is more sensitive to movement while tapping is something I will definitely investigate! I'm under the impression that it has become a lot harder to perform certain taps in other applications (mostly games) as well, so maybe this is something that Apple must fix (not that they acknowledge there is an issue ... sigh ;). – Anton Meyer Oct 01 '12 at 18:41
  • Thanks! That was my problem as well. Really weird behavior. If you have a ScrollView that should not bounce you could use `self.tableView.bounces = NO;`. – thijsai Aug 11 '14 at 10:12
6

I had the same problem. The UITableView was not triggering the didSelectRowAtIndexPath method when running in iOS6, but it was working fine in iOS5.1.

I had also implemented the

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

and returned NO. In iOS5 it was all working fine, but the minute I switched to iOS6 it would cease to trigger the didSelectRowAtIndexPath. Once I removed that shouldHighlightRow method, everything worked in iOS6 again. Cheers!

Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98
bolnad
  • 4,533
  • 3
  • 29
  • 41
5

The usual reason that didSeletRowAtIndexPath() doesn't get called is having a UITapGestureRecognizer on your viewcontroller with Cancels touches in view set to YES.

The correct and only sensible fix is to set Cancels touches in view to NO. Then your table row selection should work nicely.

Obviously this has some implications in your gesture handlers - you may need to add some code to your gesture handler to stop some touches going on to your views i.e.

- (IBAction)onTapGesture:(UITapGestureRecognizer *)sender {

    if (sender.view == someOldViewThatINeedToDealWith) {
        sender.cancelsTouchesInView = true;
    }
}
Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
Oly Dungey
  • 1,603
  • 19
  • 20
4

I tried all the other answers posted, and although they seemed promising, they didn't solve the problem.

I've since discovered the cause of problem in my case: I was calling [self.tableView reloadData] on a different thread (due to handling an NSNotification event posted from a background worker thread).

I fixed the problem by changing [self.tableView reloadData] to

[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

Hope this helps.

Andrew Newdigate
  • 6,005
  • 3
  • 37
  • 31
2

The other suspect could be a Tap Gesture Recognizer set to the view controller's view swallowing all taps like a blackhole. Remove the gesture recognizer will enable did select. I just had the same issue and the tap gesture was the cause.

naz
  • 1,478
  • 2
  • 21
  • 32
1

The resolution is really weird: the UITableViewController registered for all notifications. In the handler for the notifications, the table view data was being reloaded using

[self.tableView reloadData]

According to Apple DTS, when the table reloads data, this causes a notification to be sent to the observer, causing a race condition ...

No explanation for why it would work sometimes or why it would always work on an iPhone. But registering only for a small subset of notifications (i.e. the ones I was really interested in) fixed the problem!

Anton Meyer
  • 171
  • 1
  • 1
  • 5
1

Setting

recognizer.cancelsTouchesInView = NO;

takes care of it if your use case allows simultaneous handling of touches by [tap] gesture recognizer (kdb dismiss for example) and the view the recognizer is attached to.

Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66
  • I have a BaseViewcontroller "Parent" (with UIGestureRecognizerDelegate), and a MenuViewcontroller "Child" the latter has a TableView inside. with your line of code remove the problem of not recognizing a single touch in the tableView, because it was necessary to make Touch with two fingers to interact with the cellView, but my solution complete is: @interface MenuViewController () -(void)ViewDidLoad{ .... [self.tableViewMenu addGestureRecognizer:tapGestureRecognizer]; tapGestureRecognizer.cancelsTouchesInView = NO; – Carlos Parada Jul 10 '18 at 16:10
0

in my case I hade button which received all touch events before tableviewcell

Nikolay Shubenkov
  • 3,133
  • 1
  • 29
  • 31