4
votes

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.

5
Do you have any gesture recognisers or views on top of your cell that might be catching the taps?Guy Kogus
No one...the same code works quickly if I use a [[self navigationController] pushViewControllerRetro:schedaCliente];gdm
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
I did it, but the time profile is of litte help, because it seems that nothing is happening between two clicks :(gdm
Firt hint: if I set animation:NO, the show is in real-time! (iOS7)gdm

5 Answers

6
votes

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

 dispatch_async(dispatch_get_main_queue(), ^{ 
       // Code here 
 });
3
votes

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
votes

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

0
votes

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
votes

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