I have 4 view controllers (A,B,C,D) and they are connected in this order, and a navigation controller pointed to A. My question is is there a way for me to jump from A to C directly?
You can create a UIStoryboardSegue that connects A to C, then call performSegueWithIdentifier: with the corresponding ID in the segue to trigger it.
try Unwind segue
http://chrisrisner.com/Unwinding-with-iOS-and-Storyboards
What are Unwind segues for and how do you use them?
For Swift 3
let viewControllers: [UIViewController] = self.navigationController!.viewControllers ;
for aViewController in viewControllers {
if(aViewController is YourViewController){
self.navigationController!.popToViewController(aViewController, animated: true);
}
}
Yes, all you need to do is instantiate the view controller, then pushViewController:animated:
UINavigationController should do the rest for you, including the popping when you're ready.
hope that helps, here is the source
If you are using nib then this code will help
NSArray *viewControllersArray=[self.navigationController viewControllers];
id viewController ;
UIViewController *homeVC=nil;
for(int i=0;i<[viewControllersArray count];i++)
{viewController = [viewControllersArray objectAtIndex:i];
if([viewController isKindOfClass:[classname class]])
{ homeVC=[viewControllersArray objectAtIndex:i];
break;
}
}if(homeVC)
{
[self.navigationController popToViewController:homeVC animated:YES];
}else{
classname *objViewController=[[classname alloc]init];
[self.navigationController pushViewController:objViewController animated:YES];
[objViewController release];
}
SWIFT
if you want to go back to a particular view controller
for viewcontroller in self.navigationController!.viewControllers as Array {
if viewcontroller.isKindOfClass(HomeVC) { // change HomeVC to your viewcontroller in which you want to back.
self.navigationController?.popToViewController(viewcontroller as! UIViewController, animated: true)
break
}
}
Go like this to a particular view controller
[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:1] animated:YES];
Yes You can. For safety, let's assume that you don't know, the order in which your View Controllers are connected. So, now, you just need a class assigned to your Controller, C. Let's Say, it is ViewController_C.h.
Step 1: Go to the class inspector in storyboard and assign this ViewController_C class to the controller, C.
Step 2: Now in the View Controller class which is assigned to your controller, A, write the following method.
-(int)getViewControllerIndex{
int i=0;
for(UIViewController *vc in [self.navigationController viewControllers]){
if([vc isKindOfClass:[ViewController_C class]]){
return i;
}
i++;
}
return 0;
}
and then call this method whenever you want to jump to Controller, C.
int index = [self getViewControllerIndex];
[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:index] animated:YES];
Related
I have Collection View Controller PatientList -> on selection of cell navigates to PatientdetailView -> on click of button navigates to startDignosisView. This is Navigation controller stack. Now from Patient List I have button "ADD" that navigates to AddpatientView, from where I have to navigate to StartdignosisView without disturbing Navigation stack. How can I do it?
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[NeededViewController class]])
{
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}
if let viewControllers = self.navigationController?.viewControllers {
var newStack: [UIViewController] = []
for viewController in viewControllers {
newStack.append(viewController)
if viewController is StartdignosisView {
break
}
}
self.navigationController?.viewControllers = newStack
}
try like this:
some *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"some identifier you add to a vc in the storyboard"];
[self.navigationController pushViewController:vc animated:YES];
Just set the identifier to the storyboard for that view controller.
If you are not using storyboard then follow the below steps:
See if you Add Patient and then directly navigate to StartDignosisVC then you will not be able to pop to PatientDetailVC
You can do any one from these two:
First:
Try to present your AddPatientVC, add new and then dismiss it and follow your old stack path.
Second:
One ADD button action instantiate your AddpatientView like this:
AddPatientVC *obj = [storyboard instantiateViewControllerWithIdentifier:#"AddPatientVC"];
And similarly navigate to StartdignosisView with setting a flag that you are coming from AddPatientVC:
StartDignosisVC *obj = [storyboard instantiateViewControllerWithIdentifier:#"StartDignosisVC"];
obj.isFromAddPatientView = true
When you press Back button from StartDignosisVC then check if you came from AddPatientVC to directly pop it to Patient list.
If you are using storyboard then you can do the following see attached screen shot:
Thanks Mayank for your answer: following code worked in my case.
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0] animated:YES];
In navigation stack , i am having 6 view controllers
like
A->B->C->D->E->F
At the view controller F, I want to go back to the view controller B, how can I do this? I want to remove the view controllers one by one. Thanks in Advance!
Use this:
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[B class]])
{
[self.navigationController popToViewController:controller animated:YES];
break;
}
}
If you want to pop directly to B Class ViewController then try following.
for (UIViewController *VC in [self.navigationController viewControllers])
{
// here B is ViewCotroller Class Name
if ([VC isKindOfClass:[B class]])
{
[self.navigationController popToViewController:VC animated:TRUE];
break;
}
}
[self.navigationController viewControllers] returns the array of ViewControllers of current navigation stack. I used For (each) loop to find out our view controller (which is B ViewController) from array. If it is match than We will perform the Pop operation to that ViewController.
You can use responder chain to reach to your targetVC and pop the ones above it.
Thanks for the comments Rin and Kirandeep Kumar , i have tried like this ,it is working now
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
But i want to remove all the data in that view controller i.e objectAtindex:1
Please share how to do this
Thanks
Another answer is , for removing the viewcontroller we able to use notification also
[[NSNotificationCenter defaultCenter]postNotificationName:#"new" object:nil];
i have posted the notification in fVC and in BVC i registered and observed the notification and that method i removes the viewcontroller and clear that data
Try it:
[self.navigationController popToViewController:vcB animated:Yes];
I have a UIViewController called 'detailViewController'.
This view controller is accessed through multiple different segues using the push segue.
The problem I am facing is that the back button on the detailViewController takes the user back to the previous view controller (as it should), however I would like the back button to take the user to the masterViewController (the default UIViewController in the app).
How do I do this?
I have tried changing the segue types however that didn't really do anything at all.
Peter
The method you're looking for is UINavigationController's popToRootViewControllerAnimated:
From the documentation: "Pops all the view controllers on the stack except the root view controller and updates the display."
You'll need to create a custom back button. You can't afaik override the back button's functionality.
So something like:
UIButton *myBackButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myBackButton addTarget:self action:#selector(popToRoot:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *myCustomBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:myBackButton];
[self.navigationItem setLeftBarButtonItem:myCustomBackButtonItem];
and then the implementation of popToRoot: would look like:
- (void)popToRoot:(id)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
If the masterViewController you're talking about is the root you can call:
[self.navigationController popToRootViewControllerAnimated:YES];
You can create the back button yourself and call [self.navigationController popToRootViewControllerAnimated:YES]. However, that does require you to create the back button yourself. An alternative option could be to take the current view controller, and remove all of them except the first and current ones:
NSMutableArray *viewControllers = [self.navigationController.viewControllers mutableCopy];
[viewControllers removeObjectsInRange:NSRangeMake(1, [viewControllers count] - 2)];
self.navigationController.viewControllers = viewControllers;
Use the following code in order to go back to main view controller:
[self.navigationController popViewControllerAnimated:YES];
Edit:
Based on the comments, I realize that my code takes you only one step back and may not answer what is asked in this question. Thanks.
I came up with a workaround that looks up in a navigation controller's collection and find the offset between the existing and destination controller using name of destination controller and remove the in-between controller. Not sure if it is close to your need but give it a try:
- (NSArray *)navigateToViewController:(NSString *)destinationControllerName withControllers:(NSArray *)sourceControllers
{
NSMutableArray *controllers = [[NSMutableArray alloc] initWithArray:sourceControllers];
NSInteger sourceControllerIndex = [controllers count] - 1; // Value should be index oriented instead of position oriented.
NSInteger destControllerIndex = 0;
// Find position of destination controller (index oriented)
for (UIViewController *controller in controllers)
{
NSString *controllerName = NSStringFromClass([controller class]);
NSLog(#"class name: %#", controllerName);
if([[controllerName lowercaseString] isEqualToString:[destinationControllerName lowercaseString]])
break;
destControllerIndex +=1;
}
// If desired controller does not exists in the stack, do not proceed.
if (destControllerIndex == sourceControllerIndex)
{
return controllers;
}
// If destination is the same as source do not enter in this block
// If destination and source controllers have zero or no controllers in between do not enter in this block
// If destination and source controllers has few controllers (at least one) in between, go inside this block.
// Here "destControllerIndex + 1" shows, there is at least one controller in between source and destination.
else if(destControllerIndex + 1 < sourceControllerIndex)
{
NSLog(#"controllers in stack: %#", controllers);
// Start from the controller following the source controller in stack and remove it
// till the destination controller arrives
for (NSInteger iterator = sourceControllerIndex - 1; iterator > destControllerIndex; iterator--)
{
UIViewController *cont = [controllers objectAtIndex:iterator];
if(cont) {
[cont release]; cont = nil; }
[controllers removeObjectAtIndex:iterator];
NSLog(#"controllers in stack: %#", controllers);
}
}
return controllers;
}
and define it in some base controller:
-(void) popToViewController:(NSString *)controllerName withNavController:(UINavigationController *)navController
{
// STStatistics refers a singleton class of common functions.
NSArray *mArr = [STStatistics navigateToViewController:controllerName withControllers:navController.viewControllers];
navController.viewControllers = mArr;
// There should be more than one controller in stack to pop.
if([mArr count] > 1)
{
[navController popViewControllerAnimated:YES];
}
}
and here is how called:
[self popToViewController:#"NameOfDestinationControllerInNavStack" withControllers:self.navigationController];
In my program have 6 view controllers.(in storyboard)
Lets define 1,2,3,4,5,6.
1 is my main view.
I want to navigate like this(image bellow).Is it possible to do?
give me a idea to do this navigation.
Yes, u can implement this. This is a simple navigation in iOS using NavigationController.
you have six viewControllers 1, 2, 3, 4, 5, 6.
to do this:
First create a NavigationController and initialize it with ViewController 1 (ie a root View Controller).
Now your navigationController behaves like a stack which contains all ur pushed view controller. NavigationController is only push and pop ur view controllers.
So, every time when u want to navigation first check ur viewController is inside navigationController stack or not. If it is already in stack then pop to that controller, if not then push the same view controller.
for this use following:
In case ViewController3
-(void)popToSelectedViewController
{
NSArray *vc=[self.navigationController viewControllers];
ViewController3 *vc3=nil;
for (int i=0; i<[vc count]; i++)
{
UIViewController *tempVC=[vc objectAtIndex:i];
if([tempVC isKindOfClass:[ViewController3 class]])
{
vc=[vc objectAtIndex:i];
break;
}
}
if(vc3)
{
//If exists inside stack the pop
[self.navigationController popToViewController:vc3 animated:YES];
}
else
{
//If not exists inside stack push ViewController3
ViewController3 *vc3New= [[ViewController3 alloc]initWithNibName:#"ViewController3" bundle:nil];
[self.navigationController pushViewController:vc3New animated:YES];
[vc3New release];
}
}
For initializing ur ViewController1 with navigationController:
if using storyboard
Embed ur initialViewController(ie viewController3) with UINavigationController.
for this:
Step1: open storyboard, and select ur initialViewController(ie viewController3).
Step2: Go to Editor in menu -> Choose Embed In -> Select UINavigationController.
this creates a navigationcontroller and initializes with viewController3 as rootViewController.
if not using storyboard
make property of vc3 (ViewController3) and applicationNavigationController (UINavigationController) in .h
and in .m:
got method "application... didFinishedLaunching...." in appDelegate
and write:
self.vc3=[[ViewController3 alloc]initWithNibName:#"ViewController3" bundle:nil];
self.applicationNavigationController=[[UINavigationController alloc] initWithRootViewController:self.vc3];
self.window.rootViewController=self.applicationNavigationController;
[self.window makeKeyAndVisible];
First You create a navigation controller object
UINavigationController *navCtrl = [[UINavigationController alloc]initWithRootViewController:rootViewController];
self.window.rootViewController = navCtrl;
If you want to go to 1->2,1->3,1->6,etc, create an object for the next viewcontroller and push it to navigation stack
[self.navigationController pushViewController:second animated:YES];
You dont need to do any additional work to go back to the previous view controller. The default back button lets you go back.
If you need to return to the root view controller, then use this:
[self.navigationController popToRootViewControllerAnimated:YES];
if you want to return to any particular view controller, then use this
[self.navigationController popToViewController:viewController animated:YES];
Use UINavigationController.It is nor circular.It can be assumed as stacked approch.That is what navigation controller do
A must read for you
I have created a View based based application of 4 views. By using navigation controller I am changing the view. In my 3rd view one button is there. If I click on that button the app should come to the first view (2 views back).
I have used
[self.navigationController popViewControllerAnimated:YES];
[self.navigationController popViewControllerAnimated:YES];
This is not working. It's going to the previous page only.
for (UIViewController *controller in self.navigationController.viewControllers)
{
if ([controller isKindOfClass:[NeededViewController class]])
{
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}
Try out this, and make change according your specification
-(void)goToMainCategoryView;
{
id object = nil;
for (UIViewController *viewControl in self.navigationController.viewControllers)
{
if(viewControl.view.tag == 0)
{
object = viewControl;
}
}
[self.navigationController popToViewController:object animated:YES];
}
Another easy root to select the UIViewController by index would be to use:
NSArray *viewsArray = [self.navigationController viewControllers];
UIViewController *chosenView = [viewsArray objectAtIndex:1];
[self.navigationController popToViewController:chosenView animated:YES];
chosenView would then be the second view in the navigation stack (position 1). If you had a large stack and wanted to go a specific view.
Use
popToRootViewControllerAnimated:
to go all the way back to the top view controller:
Documentation:
Pops all the view controllers on the stack except the root view controller and updates the display.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
or
popToViewController:animated:
to go back to a particular view controller, supply the view controller you want to go to.
Documentation:
Pops view controllers until the specified view controller is at the top of the navigation stack.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
Parameters
viewController
The view controller that you want to be at the top of the stack.
The same thing in swift 1.2 :: xcode:6.4
for controller: UIViewController in self.navigationController?.viewControllers as! [UIViewController] {
if controller.isKindOfClass(YourViewController) {
self.navigationController!.popToViewController(controller, animated: true)
}
}