3

i am having issues try to manipulate the navigationstack from an ios app. Or at least with the behaviour as a result of that manipulation.

My Situation:

i have 3 ViewControllers.

Controller a shows multiple levels, Controller b is the gameview Controller c is some sort of Score

Obviously i will select a level in controller a, which triggers a segue to controller b, once the level is finished ill segue to controller c. every segue as a push.

Now once im in controller c i dont want to be able to go back to b using the back button. I want to move back to controller a. In order for this to work, i removed the controller from the stack, so back wont move to controller b. This works fine.

The issue im facing is that the backbutton does show on controller a, which seems off since there shouldn't be any back. If i click the backbutton, the app doesnt crash, the button just disappears leaving the title.

i tried adding :

    NSArray* controllers = [self.navigationController viewControllers];

    if ([controllers count]<=1) {
        [self.navigationItem setHidesBackButton:YES animated:YES];
    } else {
        [self.navigationItem setHidesBackButton:NO animated:YES];
    }
    [super viewDidAppear:animated];

as suggested in some relative stackoverflow article, without success. Besides this not working it seems off that ios creates those buttons from Storyboard without me actually adding them, but doesnt remove them when they arent necessary anymore. This leaves me with some options.

  • either i think that ios is smarter than it actually is
  • i am missing something essential to update the navigationbar
  • i went at this all wrong

besdies im using this code snipped to segue from Controller b to c.

[self performSegueWithIdentifier:@"feedbackSegue" sender:self];
[self removeFromParentViewController];

Any hints concerning missing operations or general bad practice is greatly appreciated.

Update

After further investigation, its not just the back button, its the whole navigationbar that is off. it behaves as if the removed controller was still there. The BackButton is there and another uiActionButton on the right end.

Does the navigationbar store its states onto a different stack, than the viewcontroller one? if this was the case, i could remove that state from this stack as well, to keep it consistent.

Daniel Bo
  • 2,518
  • 1
  • 18
  • 29

2 Answers2

4

You could try this in your view controller c. This will remove the previous view controller, in your case the b. You'd also have to keep b in your stack (remove the line [self removeFromParentViewController]'; )

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    if(self.navigationController.viewControllers.count>2){
        NSArray *controllers = self.navigationController.viewControllers;
        NSMutableArray *newViewControllers = [NSMutableArray arrayWithArray:controllers];
        [newViewControllers removeObject:[controllers objectAtIndex:self.navigationController.viewControllers.count - 2]];
        self.navigationController.viewControllers = newViewControllers;
    }
}
streem
  • 9,044
  • 5
  • 30
  • 41
  • this is what i was doing, leading to the same problem. The problem isnt that i actually move back to controller b. its that controller a still shows back even if there is nowhere to go back to – Daniel Bo Mar 25 '14 at 15:09
  • Well, i don't have any issue with it, be sure to add it in viewDidAppear though. – streem Mar 25 '14 at 15:12
  • 1
    i did exactly the same thing in viewdidload. im not quite sure why it does make a difference, wether you remove a previous viewcontroller in didload or didappear (can you shed some light onto that?), but it makes a difference, obviously. thanks. – Daniel Bo Mar 25 '14 at 15:47
1

I believe the "correct" way to do this is to remove the back button on controller c. Depending on how and when you are removing controller b, you may be corrupting the navigation controller stack. It's generally not a good practice to manipulate the view controller stack.

To remove the back button, you have the correct code:

self.navigationItem.hidesBackButton = YES;

However, note that you must call this before the view controller is presented -- i.e., in something like viewDidLoad.

When you want to pop back to A, use:

[self.navigationController popToRootViewControllerAnimated:YES];
Alex Medearis
  • 176
  • 1
  • 7
  • if i was to hide the backbutton, i could add one of my own, which then triggers poptorootviewcontroller. it wouldnt look any different, but from the top of my head its a viable option. ill definitely keep this as some sort of final approach in case every other attempt fails. Thanks, but im not certain that this is good practice. and if what im doing isnt good either, what would be a proper approach to achieve the desired controller behavior? – Daniel Bo Mar 25 '14 at 15:21
  • It looks like there are ways of setting your own custom left bar button that will look and behave like a back button in the way that you're describing. See: http://stackoverflow.com/questions/1214965/setting-action-for-back-button-in-navigation-controller – Alex Medearis Mar 25 '14 at 15:29
  • However, I think the real problem is that having a back button do what you're describing is breaking the flow of a navigation controller -- i.e. you want clicking back to do something other than take you back to the previous view controller. My suggestion would be to add the pop to root vc functionality to something other than a back button. – Alex Medearis Mar 25 '14 at 15:30