Replace a UIViewController in the UINavigationController hierarchy

NSMutableArray *viewController = [NSMutableArray arrayWithArray:[navController viewControllers]];
[viewController replaceObjectAtIndex:1 withObject:replacementController];
[navController setViewControllers:viewController];

See the UINavigationController class reference for more information.


A cleaner way in Swift should be:

extension UINavigationController {
  func replaceTopViewController(with viewController: UIViewController, animated: Bool) {
    var vcs = viewControllers
    vcs[vcs.count - 1] = viewController
    setViewControllers(vcs, animated: animated)
  }
}

It is not possible to animate the transition if you simply replace the viewController in the navigation controllers view controller array. I would recommend doing the following in the viewWillAppear method of the 3rd view controller.

-(void) viewWillAppear:(BOOL)animated
{
   NSArray *vCs=[[self navigationController] viewControllers];
   NSMutableArray *nvCs=nil;
   //remove the view controller before the current view controller
   nvCs=[[NSMutableArray alloc]initWithArray:vCs];
   [nvCs removeObjectAtIndex:([nvCs count]-2)];
   [[self navigationController] setViewControllers:nvCs];
   [super viewWillAppear:animated];
}

Pretty Simple, when about to push the thirdViewController instead of doing a simple pushViewController do this:

NSArray * viewControllers = [self.navigationController viewControllers];
NSArray * newViewControllers = [NSArray arrayWithObjects:[viewControllers objectAtIndex:0], [viewControllers objectAtIndex:1], thirdController,nil];
[self.navigationController setViewControllers:newViewControllers];

where [viewControllers objectAtIndex:0] and [viewControllers objectAtIndex:1] are your rootViewController and your FirstViewController.