3
votes

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?

8
assuming array items added in order View1,View3,View4,View5 ,[array objectAtIndex:2] should give you View4 nothing is wrong with that,[array objectAtIndex:0] = View1,[array objectAtIndex:1] = View3,[array objectAtIndex:2] = View4 that seems RIGHT to me, try below answer or try objectAtIndex:1u.gen
By wrong i meant i need the function [self.navigationController popToViewController:[array objectAtIndex:2] animated:NO]; always go to view3 no matter whatDim
You should use an unwind segue if you want to go back to a specific controller from different controllers or with a different stack structure.rdelmar

8 Answers

2
votes

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.

enter image description here

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,

0
votes

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.

0
votes

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]
0
votes

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
0
votes

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!

0
votes

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];
        }
    }
0
votes
for (UIViewController* controller in self.navigationController.viewControllers) {
        if ([controller isKindOfClass:[<Your View Controller Name> class]]) {
            [self.navigationController popToViewController:controller animated:YES];
            return;
        }
    }
-1
votes

Go like this to a particular view controller

  [self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:1] animated:YES];