10
votes

I'm having an incredibly frustrating problem that appears to be a bug, but I have a very hard time believing no one else has come across this. My application's root view controller is a UITabBarController, where each tab is a UINavigationController. Everything works great.

Now I've come to a place where I want to edit the stack, so I rearrange the viewControllers of the current navigation controller and then do:

[self.navigationController setViewControllers:newViewControllers animated:YES];

The stack is correctly popped/pushed to the top view controller, but the navigation bar does not update to the current view controller and seems to remain exactly as it did with the viewController before the pop. If I do:

[self.navigationController popToViewController:someViewController animated:YES];

Everything works perfectly. Has anyone ever come across this before? Is there a workaround? Something I'm doing wrong?

6
Does this bug - openradar.appspot.com/7470644 seem related?Anurag
Yes! It's the exact same bug, but that solution is quite ugly. Have you found a better workaround?beinstein
I get this bug too. Very frustrating.William Denniss
This has been filed as a bug with Apple <rdar://7791969>beinstein
I'm still experiencing this issue as of today. Example, Push screen A, then B, and in the viewDidLoad for B do: [self.navigationController setViewControllers:@[B] animated:NO]; For some reason, the issue goes away however if I hide the navigation bar before pushing the screens and then unhide it after (self.navigationController.navigationBarHidden = NO).Scott Pfeil

6 Answers

11
votes

I faced the same problem, it seems that Apple haven't corrected that bug and as a result the selected answer of this thread appears to be incorrect. I managed to correct this problem using this bug report as in the comment of Anurag combined with the comment of Scott Pfeil.

Here is the code :

navController.navigationBarHidden = YES;

NSArray* viewControllers =  navController.viewControllers;
UIViewController* currentController = [viewControllers objectAtIndex:viewControllers.count-1];

NSArray *controllers = [NSArray arrayWithObjects: viewController , currentController , nil];

[navController setViewControllers:controllers animated:NO];

navController.navigationBarHidden = NO;

I call this code in the viewDidLoad of the currentController and what I did is replace the previous controllers with only viewController.

Hope this helps.

2
votes

Apple appears to have fixed this in the newest SDK

1
votes

Two equally ugly work arounds.

First, If:

[self.navigationController popToViewController:someViewController animated:YES];

Works well, try pushing an extra viewcontroller on the stack and then call:

[self.navigationController popToViewController:someViewController animated:NO];

Meaning you should get to the vc you want without any animation.

Second,

Before setting the stack, set the leftButtonBarItem = nil; Effectively removing the old view controller's button. In fact if the title is wrong, change that too.

Neither is exactly clean but may get you the desired results.

0
votes

You can also set your root view controller as the UINavigationController's delegate like:

@interface YourViewController : UIViewController <UINavigationControllerDelegate> {

and then in the didShowViewController delegate method you manually set the available view controllers:

-(void)navigationController:(UINavigationController*)navigationController didShowViewController:(UIViewController*)viewController animated:(BOOL)animated {
    [[viewController navigationController] setViewControllers:[[viewController navigationController] viewControllers]];
}

Let me know if this works in your environment!

0
votes

I'm still facing this issue in the Xcode 9.4.1 & iOS 11.4 .

The easiest way is to call loadViewIfNeeded() for all previous view controllers in the navigation stack:

let menuViewController = ...
menuViewController.loadViewIfNeeded()

let submenuViewController = ...

navigationController.setViewControllers([menuViewController, submenuViewController], animated: true)
-2
votes
[self.navigationController setViewControllers:newViewControllers animated:NO];

this may help you.