First off, I am aware of this question being asked in a forward manner, but in this case I am asking for a backwards manner in which the Navigation Controller is already designed. With that being said...
I have a UINavigationController
with three views: Table
, Get
, and Avail
in that order that was created in IB.
When going forward, I want to go from Table
to Get
to Avail
, but when I hit the "Back" button on Avail
I want to skip over Get
and go directly back to Table
. Is this possible? If so, how?
Here's how I did it:
NSArray *VCs = [self.navigationController viewControllers];
[self.navigationController popToViewController:[VCs objectAtIndex:([VCs count] - 2)] animated:YES];
To be able to override the nav controllers's back button you're going to have to subclass UINavigationController. Check out how in this tutorial: http://www.hanspinckaers.com/custom-action-on-back-button-uinavigationcontroller
Implement the navigation controller's delegate method:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
It will fire for all VCs in the nav controller stack. (put this code in the VC immediately after your navigation controller, and put < UINavigationControllerDelegate
> in the .h
)
What you want to do is replace the entire Navigation Controller's stack without the view controller you want to remove in it. Since it's a non-mutable array, you have to convert it to a mutable array before removing the VC, remove the VC, then replace the navigation controller's stack with the call [self.navigationController setViewControllers:newVCs animated:NO];
. That's the crucial part. You are replacing the stack after you have loaded the page you are on but since you're keeping the VC you're on, it's still the top item on the stack so there is no visible impact to the user. As long as you don't have a lot of VCs on the stack, it's not an expensive call.
Here's how I did it in the delegate method:
//Remove list setup page if new list was created
if ([self.navigationController topViewController].class == [ItemViewController class])
{
NSArray *VCs = [self.navigationController viewControllers];
if(((UITableViewController*)[VCs objectAtIndex:[VCs count]-2]).class == [NewCardTypeController class])
{
NewCardTypeController *removedObject = [VCs objectAtIndex:[VCs count]-2];
if(removedObject != nil)
{
NSMutableArray *newArray = [NSMutableArray arrayWithArray:VCs];
[newArray removeObject:removedObject];
NSArray *newVCs = [NSArray arrayWithArray:newArray];
[self.navigationController setViewControllers:newVCs animated:NO];
}
}
}
Take a look at UINavigationController's -popToViewController:animated:
and -popToRootViewControllerAnimated:
, which do exactly what you're asking for. That is, they pop the navigation stack back to a particular view controller, or to the root view controller. You'll still need to intercept the nav controller's back button action to use them, though.