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];
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];
I'm using a storyboard and storyboard id's, I'm several controllers deep in the navigation stack.
Menu Controller
Selection Controller
Item Controller
Result Controller
I'm currently on the 'Result Controller' and I want go to the 'Item Controller', but reset / reload that controller, I would be passing in the same property values that it currently has. So in effect I would be going up two levels then push.
I just wondered whats the best way to achieve this?
I guess I could call pop a couple of times then push within my 'Result Controller' passing property values to the 'Item Controller'?
Hmm, I guess I would have keep the animation for the first pop then disable it for the two pushes.
Hope this makes sense.
Try this. Maybe it will help you.
NSArray *vList = [[self navigationController] viewControllers];
UIViewController *view;
for (int i=[vList count]-1; i>=0; --i) {
view = [vList objectAtIndex:i];
if ([view.nibName isEqualToString: #"ItemController"])
{
[self.navigationController popToViewController:view animated:YES];
break;
}
}
for (UIViewController *controller in [self.navigationController viewControllers])
{
if ([controller isKindOfClass:[YourViewCOntrollerName class]])
{
[self.navigationController popToViewController:controller animated:YES];
break;
}
}
Try this
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:2] animated:YES];
you can go back at any index you want
Pop to specific view controller( in this case ItemController) you can use below code
[self.navigationController popToViewController:ItemController animated:YES];
The way you try to make it is not really optimal, and could end up causing you problems. The clean way to do this would be to code a way to reset the "Item Controller" so you just have to do 1 pop.
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];
I need to jump between view controllers. For example:
View1: First screen (Just logo)
View2: Download Screen
View3: First app screen (Some Buttons)
View4-View(N): some app screens
When user enters app the app goes to View1->View2 (downloads stuff)->View 3->View4->View5
Then user wish to go to First app screen (View3) he does:
NSArray *array = [self.navigationController viewControllers];
[self.navigationController popToViewController:[array objectAtIndex:2] animated:NO];
The first time user enters the app it goes: View1->View3 (The download screen no longer needed), and I have different push segue to go to View3 so lets assume the user goes to: View1->View 3->View4->View5, now he wishes to go back to View3, so the function:
NSArray *array = [self.navigationController viewControllers];
[self.navigationController popToViewController:[array objectAtIndex:2] animated:NO];
Will return him to View4, and this is WRONG. How can I solve it?
Well if you are using storyboards , what you can do is set your uiviewcontrollers' storyboard id and use it for popping and pushing your views.
Lets say your Storyboards name is MainStoryboard.storyboard
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil];
SettingsListViewController *settingsVC = [sb instantiateViewControllerWithIdentifier:#"SettingsListViewController"]; // #"SettingsListViewController" is the string you have set in above picture
[self.navigationController popToViewController:settingsVC animated:YES];
Above solution should work for you , but If I were you I would change the structure of my app , you say :
View1: First screen (Just logo)
View2: Download Screen
Since View1 is just logo and View 2 is also a view that you skip, you can remove them from navigation controller and make View3 your navigation controller's root view controller and when you need view1 and view2 present them as Modal View Controllers,
when you are done with them lets say; user successfully loaded the app dismiss logo screen and present Download Screen if download successful then dismiss it.
So your View3 Will be there as root view controller, lets say your at View(n) you want to go to home screen which is View3 all you need to do is call
[self.navigationController popToRootViewControllerAnimated:NO];
When you are on view(n) and want to pop to view(n-1) just use
[self.navigationController popViewControllerAnimated:YES];
good luck,
I always use this, and it will work fine in your case. In fact the following line of code is copied to my "Notes" for quick copy/paste.
Be sure to import your ViewController.h file, if not.
for (UIViewController *viewController in self.navigationController.viewControllers) {
if([viewController isKindOfClass:["your ViewController" class]]) {
[self.navigationController popToViewController:viewController animated:NO];
}
}
In the second sequence your navigation stack changes and view3 would be at index 1. so
[[self.navigationController popToViewController:[array objectAtIndex:1] animated:NO];
would be the right way of doing it.
according to your sitation use directly name of viewController
create instance of your viewController,like this
i supposed here that your viewController name is-view3Controller
View3Controller view3Controller=[[View3Controller alloc]init];
[self.navigationController popToViewController:#"view3Controller" animated:NO]
or if you are using storyboard then
View3Controller view3Controller=[self.storyboard instantiateViewControllerWithIdentifier:#"view3Controller"];
[self.navigationController popToViewController:#"view3Controller" animated:NO]
It sounds like View 2 is not being added to your view controllers array at run time, possibly because of the segue you've created.
Try removing the segue that transitions from View 1 > View 3 and pushing the user past View 2 without animating, as your application's logic requires it:
// If the user needs to skip ahead to view 3, conditionally push view 2 and view 3 without animating
[self.navigationController pushViewController:viewController2 animated:NO];
[self.navigationController pushViewController:viewController3 animated:NO];
Alternatively if you left the segue in place could you not look at the size of the UINavigationController viewControllers property and "guess" based on the size whether or not you skipped View 2? If you did then you can adjust the popToViewController method to pop to the correct index. This is, admittedly less elegant and brittle if you need to skip other views as well.
// Check length of viewController array with 'N' views (pseudo code)
if (self.navigationController.viewControllers.length == N-1)
// View 2 was ignored: pop to objectAtIndex:1
else
// View 2 was included: pop to objectAtIndex:2
If I understood you correctly, your view3 has special view controller, so you can use such code:
NSArray *VCs = [self.navigationController viewControllers];
for (UIViewController *VC in VCs)
{
if ([VC isKindOfClass:[**YOUR-VIEW-CONTROLLER** class]]) {
[self.navigationController popToViewController:VC animated:NO];
}
}
It's simple and it works!
for (UIViewController* controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[<Your View Controller Name> class]]) {
[self.navigationController popToViewController:controller animated:YES];
return;
}
}
Go like this to a particular view controller
[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:1] animated:YES];
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)
}
}