Getting "nested push animation can result in corrupted navigation bar"

ios, iphone, objective-c, xcode

Solution

Your issue is most likely in `tableView:didSelectRowAtIndexPath` in `TCGSetViewController.m`.

You have an `if` statement followed by an `if else` statement. When `indexPath.row == 0` the first `if` is true, which performs `[self performSegueWithIdentifier:@"showFlashFireSet" sender:self]`. But then code execution continues into the `if else` block. You have two separate execution blocks there. Since `indexPath.row` is still 0, we'll enter the `else` block, and another segue is performed.

You most likely want that to be structured as

if (indexPath.row == 0)
{
    [self performSegueWithIdentifier:@"showFlashFireSet" sender:self];
}
else if (indexPath.row == 1) // notice the else on this line
{
    [self performSegueWithIdentifier:@"showXYBaseSet" sender:self];
}
else
{
    [self performSegueWithIdentifier:@"showLegendarySet" sender:self];
}

Even better, put it in a switch statement:

NSString *segueID = nil;
switch (indexPath.row) {
    case 0:
        segueID = @"showFlashFireSet";
        break;
    case 1:
        segueID = @"showXYBaseSet";
        break;
    default:
        segueID = @"showLegendarySet";
        break;
}
[self performSegueWithIdentifier:segueID sender:self];

P.S.: More comments

As of iOS 5 or 6 or 7 or something, `dequeueReusableCellWithIdentifier:forIndexPath:` is guaranteed to return a valid cell, so it's unnecessary to check for `cell == nil` after calling that method (assuming you're not targeting an old iOS version).

I see you're just calling `dequeueReusableCellWithIdentifier:` though, which does have the possibility of returning `nil`. BUT you're calling that method twice in the code you've posted, and both times within a `tableView` datasource method that has an `indexPath` available to use, so take advantage of it and delete those `if (cell == nil)` checks; it's liberating.

Problem

I am completely stuck. I've been searching around SO for answers and it seems like everyone has a different problem for each "nested push animation can result in corrupted navigation bar" error. Keep in mind I am trying to teach myself how to code for iOS 7. So if some of my coding methods are not ideal, I'm sorry and please provide feedback. Anyways, I'm creating a Pokemon Trading Card Game Pokedex app that shows cards from the most recent sets. Everything is working flawlessly except for when I select the very first table cell on the main screen (XY Flash Fire). It will show the correct table data, but the navigation bar title is incorrect. Also it wont go to the PokedexDetailViewController when I select a row. Again, all other table cells from the main screen work with no issues. I also tried other fixes and classes that people posted on here and github, but none worked for me. I also recreated the whole FlashFireViewController and still having the same issues. Made sure all of the code is pretty much identical with the other working view controllers. Also verified that the segues are coming from the Set View Controller, oppose to the cells. However, once its in Flash Fire View Controller, the segues originates from the cell. Cant post pics yet, so here is an album link to my screen shots: https://i.stack.imgur.com/MaJqE.jpg - How my storyboard is set up. - The main screen once the app is launched. - When I select the second cell (XY). - When I select Mega Venusaur EX. - **The error. When I select the first cell (XY Flash Fire). It shows the correct table data, but not the correct navigation title. - When I select Butterfree, or any other pokemon, nothing happens and the navigation title disappears. Also, once I hit back, the app crashes and stops. Here is the code for TCGSetViewController.m which is the class for the main screen. ``` @interface TCGSetViewController () @end @implementation TCGSetViewController{ NSArray *thumbnailCell; } @synthesize tableView = _tableView; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. thumbnailCell = [NSArray arrayWithObjects:@"XYFlashFire.png", @"XYBaseSet.png", @"BWLegendaryTreasures", @"BWPlasmaBlast.png", @"BWPlasmaFreeze.png", @"BWPlasmaStorm.png", nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [thumbnailCell count]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 61; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *simpleTableIdentifier = @"PokemonSetCell"; TCGSetCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; if (cell == nil) { cell = [[TCGSetCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier]; } cell.setImage.image = [UIImage imageNamed:[thumbnailCell objectAtIndex:indexPath.row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Conditionally perform segues, here is an example: if (indexPath.row == 0) { [self performSegueWithIdentifier:@"showFlashFireSet" sender:self]; } if (indexPath.row == 1) { [self performSegueWithIdentifier:@"showXYBaseSet" sender:self]; } else { [self performSegueWithIdentifier:@"showLegendarySet" sender:self]; } } ``` And here is the code for FlashFireViewController.m, which is the first table cell. ``` @interface FlashFireViewController () @end @implementation FlashFireViewController{ NSArray *pokemons; NSArray *searchResults; } @synthesize tableView = _tableView; - (void)viewDidLoad { [super viewDidLoad]; Pokemon *caterpie = [Pokemon new]; caterpie.name = @"Caterpie"; caterpie.hitPoints = @"40 HP"; caterpie.setNumber = @"1/106"; caterpie.imageFile = @"1-caterpie.jpg"; caterpie.rarity = @"COMMON"; Pokemon *metapod = [Pokemon new]; metapod.name = @"Metapod"; metapod.hitPoints = @"70 HP"; metapod.setNumber = @"2/106"; metapod.imageFile = @"2-metapod.jpg"; metapod.rarity = @"UNCOMMON"; Pokemon *butterfree = [Pokemon new]; butterfree.name = @"Butterfree"; butterfree.hitPoints = @"130 HP"; butterfree.setNumber = @"3/106"; butterfree.imageFile = @"3-butterfree.jpg"; butterfree.rarity = @"RARE"; Pokemon *pineco = [Pokemon new]; pineco.name = @"Pineco"; pineco.hitPoints = @"60 HP"; pineco.setNumber = @"4/106"; pineco.imageFile = @"4-pineco.jpg"; pineco.rarity = @"COMMON"; Pokemon *seedot = [Pokemon new]; seedot.name = @"Seedot"; seedot.hitPoints = @"50 HP"; seedot.setNumber = @"5/106"; seedot.imageFile = @"5-seedot.jpg"; seedot.rarity = @"COMMON"; Pokemon *nuzleaf = [Pokemon new]; nuzleaf.name = @"Nuzleaf"; nuzleaf.hitPoints = @"80 HP"; nuzleaf.setNumber = @"6/106"; nuzleaf.imageFile = @"6-nuzleaf.jpg"; nuzleaf.rarity = @"UNCOMMON"; Pokemon *shiftry = [Pokemon new]; shiftry.name = @"Shiftry"; shiftry.hitPoints = @"140 HP"; shiftry.setNumber = @"7/106"; shiftry.imageFile = @"7-shiftry.jpg"; shiftry.rarity = @"RARE"; Pokemon *roselia = [Pokemon new]; roselia.name = @"Roselia"; roselia.hitPoints = @"60 HP"; roselia.setNumber = @"8/106"; roselia.imageFile = @"8-roselia.jpg"; roselia.rarity = @"COMMON"; Pokemon *roserade = [Pokemon new]; roserade.name = @"Roserade"; roserade.hitPoints = @"90 HP"; roserade.setNumber = @"9/106"; roserade.imageFile = @"9-roserade.jpg"; roserade.rarity = @"UNCOMMON"; Pokemon *maractus = [Pokemon new]; maractus.name = @"Maractus"; maractus.hitPoints = @"90 HP"; maractus.setNumber = @"10/106"; maractus.imageFile = @"10-maractus.jpg"; maractus.rarity = @"UNCOMMON"; pokemons = [NSArray arrayWithObjects:caterpie, metapod, butterfree, pineco, seedot, nuzleaf, shiftry, roselia, roserade, maractus, nil]; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView == self.searchDisplayController.searchResultsTableView) { return [searchResults count]; } else { return [pokemons count]; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *pokemonTableIdentifier = @"PokemonTableCell"; TCGPokedexCell *cell = (TCGPokedexCell *)[self.tableView dequeueReusableCellWithIdentifier:pokemonTableIdentifier]; if (cell == nil) { cell = [[TCGPokedexCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:pokemonTableIdentifier]; } Pokemon *pokemon = [pokemons objectAtIndex:indexPath.row]; if (tableView == self.searchDisplayController.searchResultsTableView) { pokemon = [searchResults objectAtIndex:indexPath.row]; } else { pokemon = [pokemons objectAtIndex:indexPath.row]; } cell.pokemonLabel.text = pokemon.name; cell.pokemonNum.text = pokemon.setNumber; cell.thumbnailImageView.image = [UIImage imageNamed:pokemon.imageFile]; cell.pokemonHP.text = pokemon.hitPoints; cell.pokemonRarity.text = pokemon.rarity; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 61; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"showPokedexDetail"]) { NSIndexPath *indexPath = nil; Pokemon *pokemon = nil; if (self.searchDisplayController.active) { indexPath = [self.searchDisplayController.searchResultsTableView indexPathForSelectedRow]; pokemon = [searchResults objectAtIndex:indexPath.row]; } else { indexPath = [self.tableView indexPathForSelectedRow]; pokemon = [pokemons objectAtIndex:indexPath.row]; } PokedexDetailViewController *destViewController = segue.destinationViewController; destViewController.pokemon = pokemon; } } - (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope { NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchText]; searchResults = [pokemons filteredArrayUsingPredicate:resultPredicate]; } -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { [self filterContentForSearchText:searchString scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]]; return YES; } @end ``` Here is the exact error code I'm getting: ``` 2014-07-08 12:38:18.409 TCG Pokedex[37666:60b] nested push animation can result in corrupted navigation bar 2014-07-08 12:38:18.849 TCG Pokedex[37666:60b] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted. 2014-07-08 12:38:22.222 TCG Pokedex[37666:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't add self as subview' *** First throw call stack: ```

Original source