4

Very very strange! It works everywhere but here:

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{
 MyViewController* cliente = [[MyViewController alloc] initWithModeAndClientId:2 c:cid];

            cliente.delegate                    = self;
            UINavigationController *n = [[UINavigationController alloc] initWithRootViewController:cliente];

            n.navigationBarHidden     = NO;
            [[n navigationBar] setBarStyle:UIBarStyleBlack];
            [self presentViewController:n animated:YES completion:nil];
}

If I tap by a single click on the row, the MyViewController shows after seconds! If I click twice, it shows rapidly! In the Profiler, at single click nothing happens... I have no didDeselectRowAtIndexPath method.

gdm
  • 7,647
  • 3
  • 41
  • 71
  • Do you have any gesture recognisers or views on top of your cell that might be catching the taps? – Guy Kogus Nov 22 '13 at 16:06
  • No one...the same code works quickly if I use a [[self navigationController] pushViewControllerRetro:schedaCliente]; – gdm Nov 22 '13 at 16:10
  • Could your view controller initialisation code be blocking? Use Instruments -> Time Profiler to see if any of your code is taking a significantly long time. – Guy Kogus Nov 22 '13 at 16:11
  • I did it, but the time profile is of litte help, because it seems that nothing is happening between two clicks :( – gdm Nov 22 '13 at 16:21
  • Firt hint: if I set animation:NO, the show is in real-time! (iOS7) – gdm Nov 22 '13 at 16:34

5 Answers5

6

The solution is to put on the main thread the loading of the second controller

 dispatch_async(dispatch_get_main_queue(), ^{ 
       // Code here 
 });
gdm
  • 7,647
  • 3
  • 41
  • 71
  • Do you receive the tableView: didDeselectRowAtIndexPath: on a different thread than the main? – Szabi Tolnai Nov 22 '13 at 17:21
  • Sorry, I meant tableView:didSelectRowAtIndexPath:. I just would like to see why the dispatch_async made this work. Either it is something to do with threading or with animations. – Szabi Tolnai Nov 24 '13 at 18:55
  • 2
    Well, didSelect is on the main thread, I suppose. How it could be on a different thread? – gdm Nov 26 '13 at 11:36
2

Its issue of threading, when you tap a row in tableview it start a new thread so the presenting a view may take longer to show up on screen.

The solution is:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    dispatch_async(dispatch_get_main_queue(), ^{

        MyViewController* cliente = [[MyViewController alloc] initWithModeAndClientId:2 c:cid];

        cliente.delegate = self;
        UINavigationController *n = [[UINavigationController alloc] initWithRootViewController:cliente];

        n.navigationBarHidden = NO;
        [[n navigationBar] setBarStyle:UIBarStyleBlack];
        [self presentViewController:n animated:YES completion:nil];
    });
}
0

Are you by any chance putting a tableview inside a scroll view? If so the container scrollview is blocking the touch event to the inner table view. This fixed it for me:

self.myContainerScrollview.panGestureRecognizer.delaysTouchesBegan = true

Credit for the answer should go to the OP here: https://stackoverflow.com/a/31040918/1455770

Community
  • 1
  • 1
Robert Wagstaff
  • 2,664
  • 1
  • 27
  • 40
0

Had the same problem. And it was hard to find. But it was because of following:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
        return nil;
}

You should return indexPath

0

I had the same issue on my tableView(swift 4.2). After debugging and taking lots of time it appeared that table view has a boolean property named allowsMultipleSelection.

If allowsMultipleSelection is set to true the table view selection mechanism will change in a way that by selecting each cell the tableView didSelectRowAtIndexPath: is called for the first time and by selecting the same cell for the second time the tableView didDeselectRowAtIndexPath: is called.

This makes tableView didSelectRowAtIndexPath: function to be called on the third selection for the same cell and so the result is double tap for calling didSelectRowAtIndexPath:.

It means that if the number of times a cell tapped are odd (1, 3, 5, ...) then always tableView didSelectRowAtIndexPath: will be called and if the number of times a cell tapped are even (2, 4, 6, ...) then always tableView didDeselectRowAtIndexPath: will be called.

If you want the tableView didSelectRowAtIndexPath: to be called on each selection for a cell then the tableView multiple selection has to be set false, tableView.allowsMultipleSelection = false.

By doing this, every time the cell is tapped tableView didSelectRowAtIndexPath: will be called on table view and by selecting another cell tableView didDeselectRowAtIndexPath: will be called for the cell was selected before and then the tableView didSelectRowAtIndexPath: will be called for the newly selected cell.

    class TableViewController: UITableViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.allowsMultipleSelection = false
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("This will be called for each cell tap")
    }