view controller A B C D
A -> B -> C-> D
popViewController only form D to C
popViewTopController only form D to A;
Any way can I pop to any view as I wish if I have 10 view controllers?
Thanks for everyone. will the popViewController pop to a new view Controller ?
Option 1: Select by class
To tell the navigationController to pop to a specific class, you can do as follows:
NSArray *allViewControllers = [self.navigationController viewControllers];
for (UIViewController *aViewController in allViewControllers)
{
if ([aViewController isKindOfClass:[B class]])
{
[self.navigationController popToViewController:aViewController animated:YES];
}
}
Take into account that you should only use this, if you are not pushing instances of the same class several times.
Option 2: Select by level
If you want to pop to a specific level, you can just select it by index at self.navigationController.viewControllers since it correspond to the levels. The first pushed UIViewController will be at index 0, the second at index 1 and so on:
NSArray *allViewControllers = [self.navigationController viewControllers];
UIViewController *aViewController = [allViewControllers objectAtIndex:level];
[self.navigationController popToViewController:aViewController animated:YES];
if you want to pop any view you want to change objectAtIndex:1,2,3..etc
it will pop to first,second etc... from the any views.
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
This is the method you are looking for (reference)
In Obj-c
- (NSArray *)popToViewController:(UIViewController *)viewController
animated:(BOOL)animated
You should pass in the view controller that you want pop to
Use the following UINavigationController method to go to any view controller on the current stack.
- (NSArray *)popToViewController:(UIViewController *)viewController
animated:(BOOL)animated
For example, if you are in a UIViewController and you want to pop back to the third one in the stack:
UINavigationController * nc = self.navigationController;
UIViewController * popToVC = [nc.viewControllers objectAtIndex:2];
[nc popToViewController:popToVC animated:YES];
SecondViewController *sec = [SecondViewController alloc] init];
[self.navigationController popViewController:Sec animated:YES];
Related
I have three UIViewControllers. I am navigating to VC3 from VC1. I want to navigate to VC2 if I click on cancel or done button from VC3.
I have added the VC2 controller to navigation stack programmatically.
DocListViewController *temp1 = [[DocListViewController alloc] initWithNibName:#"DocListViewController" bundle:nil];
[self.navigationController addChildViewController: temp1];
for (UIViewController *controllers in self.navigationController.viewControllers) {
if([controllers isKindOfClass: [DocListViewController class]]) {
DocListViewController *VC2ViewController = (DocListViewController*)controllers;
[self.navigationController popToViewController:VC2ViewController animated:YES];
}
}
What you are doing wrong here is adding it as child view controller,addChildViewController as it as a child of the current view controller does not add it in the navigation stack.
You need to insert the controller in you navigation stack before doing popToViewcontroller.
VC2 *temp1 = [[VC2 alloc] initWithNibName:#"DocListViewController" bundle:nil];
NSMutableArray *vcArray = [NSMutableArray arrayWithArray:self.navigationController.viewControllers] ;
[vcArray insertObject:temp1 atIndex:1]; // ** This index is `1` assuming you only have 2 controllers and we are pushing it in the middle,
// if you have many vc in navigation stack and just want to insert a new vc just before your current vc go with this:
/*
[vcArray insertObject:temp1 atIndex:vcArray.count - 2];
*/
self.navigationController.viewControllers = vcArray;
/* --- ** This part is also not needed:
for (UIViewController *controllers in self.navigationController.viewControllers) {
if([controllers isKindOfClass: [DocListViewController class]]) {
[self.navigationController popToViewController: controllers animated:YES];
}
}
*/
[self.navigationController popViewControllerAnimated:true];
Also: you don't need VC2 *VC2ViewController = (VC2*)controllers;
inside the if block as you only need a UIViewController type object for pop-ing.
I have just edited your code, get the project reference below
Edit:
Adding GitHub link for better reference:
PlayingWithNavigation
You can navigate to VC2 using pushviewContoller
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
VC2 * VC2View = [storyboard instantiateViewControllerWithIdentifier:#"VC2ID"]; // "VC2ID" is the storyboard Id of your view controller
[self.navigationController pushViewController:VC2View animated:YES];
UIViewController *vc2 = [[UIViewController alloc] init];
UIViewController *vc3 = [[UIViewController alloc] init];
[self.navigationController pushViewController:vc2 animated:NO];
[self.navigationController pushViewController:vc3 animated:YES];
Try this.
I have a very weird problem with the UINavigationController on iOS 8, maybe someone encountered this already and can shed some light. I have 2 views: let's say view A and view B
I am using it like this:
view A [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
push to a new view B [self.navigationController pushViewController:vc animated:YES];
return to view A [self.navigationController popToRootViewControllerAnimated:YES];
The problem is that if I play with this for 2 min and go through this like push-push-push-push-pop and again... at some time it stops animating, for either push and pop.
I checked the 1) view controllers they get deallocated on the pop to root, 2) I don't receive any memory warnings, 3) the navigation controller is the rootviewcontroller of the window so why this problem?
I can't find any explanation maybe someone has encountered this already. Also I am mentioning I am not using custom animations, just the plain native push and pop of a normal UIViewController, not even subclassing that so everything is plain native.
#kokos8998 try using
#interface AnimatorPushGalleryToGallery : NSObject <UIViewControllerAnimatedTransitioning>
and then in view A just add this and will control everything from view B either A->B or B->A (or in case you need something more custom add the same delegate in B as well)
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.delegate = self;
}
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
{
if(operation == UINavigationControllerOperationPush)
return [AnimatorPushGalleryToGallery new];
else if(operation == UINavigationControllerOperationPop)
return [AnimatorPopGalleryToGallery new];
return nil;
}
I am using doing something basic like this to push to a view.
UIStoryboard *storyboard = self.navigationController.storyboard;
MenuViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"menuViewController"];
[self.navigationController pushViewController:viewController animated:YES];
Some places I can simply use:
[self.navigationController popViewControllerAnimated:YES];
But in a few places I want to pop to a specific view controller. What I have tried is:
UIStoryboard *storyboard = self.navigationController.storyboard;
RecordMenuViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"recordMenuViewController"];
[self.navigationController popToViewController:viewController animated:YES];
But it just goes to a black screen like the view isn't in the stack or something. What am I missing here?
If you want to pop to a specific view controller using the navigation stack, do the following:
NSArray* vcs = self.navigationController.viewControllers;
UIViewController* target = [vcs objectAtIndex:([vcs count] - 1) - numVCsToGoBack];
[self.navigationController popToViewController:target];
If you have to pop to specific view controller in the stack use following code:
(here consider you have to pop to MyViewController Class)
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[MyViewController class]])
{
[navigationController popToViewController:controller animated:YES];
break;
}
}
I have problem in navigating from one view controller to other.
what I'm doing is If suppose there are 3 view controllers A,B,C then from A I'm pushing to B.
But in B view did load I'm hitting one api and if status code is not 200 I'm pushing to C.
But my problem is only navigation title of C is appearing and every thing is B's view.
Here is code:
NSLog(#"~~~~~ Status code: %d", [urlResponse statusCode]);
NSLog(#"Error: %#", [NSHTTPURLResponse localizedStringForStatusCode: urlResponse.statusCode]);
if([urlResponse statusCode]!=200)
{
TermsAndConditions * view = [self.storyboard instantiateViewControllerWithIdentifier:#"TermsAndConditions"];
self.navigationController.navigationBar.topItem.title = #"";
[self.navigationController pushViewController:view animated:YES];
}
Just drag from a button or any other object to another viewController in stroyboard. it is the simple way.
and the another method is
Import The viewController example: #include "SecondViewController"
then define it in .m file where u want to take the navigation
SecondViewController *tempVC =[[SecondViewController alloc]
initWithNibName:#"homeViewController" bundle:nil];
[self.navigationController pushViewController:tempVC animated:YES];
but here pushViewController does not carry the navigation properties if u need navigation properties in SecondViewController write like this
SecondViewController *tempVC =[[SecondViewController alloc]
initWithNibName:#"homeViewController" bundle:nil];
[self.navigationController presentedViewController:tempVC animated:YES]
it works for your definitely.
In my app I'm implementing UINavigationController. There are several UIViewControllers that are being pushed in the stack.
When I reach the last one, I wish to have (upon a user action) all the UIViewControllers be popped except for the first UIViewController. How do I do that?
I understand how to pop the last one, but how do I instruct all the previous ones to disappear as well?
You can try the popToRootViewControllerAnimated:, popToViewController:animated: and popViewControllerAnimated: messages of the UINavigationController class.
In your case it is really usefull to use popToRootViewcontrollerAnimated: as suggested by Irene, but if somebody need to pop exact number of controllers, then following code can be usefull:
- (void) popControllersNumber:(int)number
{
if (number <= 1)
[[self navigationController] popViewControllerAnimated:YES];
else
{
NSArray* controller = [[self navigationController] viewControllers];
int requiredIndex = [controller count] - number - 1;
if (requiredIndex < 0) requiredIndex = 0;
UIViewController* requireController = [[[self navigationController] viewControllers] objectAtIndex:requiredIndex];
[[self navigationController] popToViewController:requireController animated:YES];
}
}
Use
TravelViewController *travelView = [self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-3];
[self.navigationController popToViewController:travelView animated:YES];