Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent UITableView from receiving two touches (nested pop animation can result in corrupted navigation bar)

I am using a UITableView in my app, which when tapped will use UINavigationController to push another view controller onto the navigation controller's view controller stack.

However, when a cell on the tableview is double †apped, tableView:didSelectRowAtIndexPath: gets called twice, causing the navigation controller to push two of these new viewcontroller s on the stack and resulting in the following console output:

nested pop animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

It's not a very important issue, because users are not very likely to perform a double tap on the table view cells, however I was wondering if there is an elegant solution to prevent this kind of misnavigation? (maybe checking the navigation controller's topViewController and subsequently decide whether the push pushViewController: method should actually be performed?).

like image 390
nburk Avatar asked May 27 '14 12:05

nburk


4 Answers

Just set userInteractionEnabled to NO like this

in your viewWillAppear

-(void)viewWillAppear:(BOOL)animated
{

  // if you return from another viewController
  [tableView setUserinteractionEnabled:YES];

}

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

  // do your logic here and at the end just set user interaction to NO
  [tableView setUserInteractionEnabled:NO];

}

This will block all user interactions with your tableview.

like image 91
Pancho Avatar answered Nov 10 '22 13:11

Pancho


Here is one line solution

self.tableView.multipleTouchEnabled = NO;
like image 43
l0gg3r Avatar answered Nov 10 '22 13:11

l0gg3r


A fix I've found for the issue described here is wrapping all my didSelectRowAtIndexPath code inside the following check:

    if ([[self navigationController] topViewController] == self) {
        [your existing didSelectRowAtIndexPath code here]
    }

This checks to see whether another view controller has already been pushed to the top of the view controller stack (and is still waiting to actually appear on screen for some reason).

I believe that the multiTouchEnabled property mentioned elsewhere actually refers to the multi-touch feature, which allows iOS to register several touch events simultaneously (for example, pinch-to-zoom using two fingers on the screen at the same time) rather than multiple sequential touches.

like image 7
Jordan Sorensen Avatar answered Nov 10 '22 11:11

Jordan Sorensen


Jordan Sorensen modernized to swift:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
    if self.navigationController?.topViewController == self
    {
        self.performSegueWithIdentifier("whatever", sender:self)
    }
    else{
        // uncomment to break in else case print("fasttaper's superfluous input was ignored")
    }
}
like image 7
Anton Tropashko Avatar answered Nov 10 '22 13:11

Anton Tropashko