2

I have a table view controller, A, which does a push segue to a view controller, B. B then does a modal segue to a view controller C. I have a button on C which needs to result in the dismissal of C (which is modal as stated) and ALSO the popping of B so that we go back to A. In C, I have detected the button press and used a delegate to call back to B which then dismisses the modal view controller C using this:

[sender dismissViewControllerAnimated:NO completion:nil];

B then uses a delegate to call back to A which pops B from the stack using this:

[self.navigationController popViewControllerAnimated:YES];

Now this all works, except for the very annoying fact that I briefly see B during all this, whereas I would like to be able to "pop" from C straight back to A without seeing B at all, however briefly. I have tried combinations of YES/NO for the Animated parameters above and also tried popToRootViewControllerAnimated, but no luck :-(

Does anybody have any ideas?

ZingMaster
  • 21
  • 1

4 Answers4

1

I threw together a quick project, and it seemed to work fine for me using this code:

[self dismissViewControllerAnimated:YES completion:nil];
// Just a coincidence that this is the presenting VC rather than a regular UIViewController I think. 
UINavigationController *navController = (UINavigationController *)self.presentingViewController;
[navController popViewControllerAnimated:NO];

This is the example project on Github: https://github.com/MaxGabriel/iOSNavigationFlow

MaxGabriel
  • 7,617
  • 4
  • 35
  • 82
  • Thanks Max. Almost what I wanted - sorry I should have pointed out that I want a left-to-right transition back to A rather than a top-down transition as your example shows, which is why I was using Animated NO and YES in the order I specified. I downloaded your example code and played around with the YES/NO and when I set it up like mine, I get the left-to-right transition ok, but I still see the nav bar of B as it transitions back to A. I'm now wondering if it's even possible to go back from C to A with anything other than a "reverse modal" (i.e. top-to-bottom) transition. What do you think? – ZingMaster Dec 16 '12 at 08:25
  • You would probably need to create a custom animation that replicates the `pop` animation. Is there a reason you don't just push `C` onto `B` and then `popToViewController:A animated:YES`? It doesn't really make sense from a design perspective that `C` would slide up from the bottom, but then to get back to `A` you do a popping animation. – MaxGabriel Dec 16 '12 at 16:23
  • My design is that A is a list of entities, eg. Persons. B shows the detail of a Person and C lets you edit that Person. The button on C is to delete a Person and to me it looks a bit better to slide A back in from the left when that happens, rather than the modal C sliding back down as the user expectation is that the view that got them to C (i.e. B) should be under it, which it isn't in this case. Your comments got me thinking, though, that maybe I should "morph" B into appearing like C, the way iPhone Contacts does it, and therefore only have 2 controllers instead of 3. Thanks for your help! – ZingMaster Dec 16 '12 at 21:06
0
[self.navigationController popViewControllerAnimated:NO];
Vishal Singh
  • 4,400
  • 4
  • 27
  • 43
0

You can do what you want with the following code. First, you popToRootViewController which takes controller B off the stack, but doesn't change the view, since C's view is up. Then you add the navigation controller's view underneath C's view so it's in the view hierarchy, but not visible. Then you do an animation to slide C's view off to the right, and finally, you dismiss the modal view controller. I created a property, nav, to make the typing shorter, but it's not really necessary. This code is in the modal view controller's .m

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.nav = (UINavigationController *)self.presentingViewController;
}

-(IBAction)goBackToRoot: (UIButton *) sender {
    [self.nav popToRootViewControllerAnimated:NO];
    [self.view.window insertSubview:self.nav.view belowSubview:self.view];
    [UIView animateWithDuration:.6 animations:^{
        self.view.frame = CGRectMake(330, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    } completion:^(BOOL finished) {
        [self.nav dismissViewControllerAnimated:NO completion:nil];
    }];
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Thanks. That code made me think :-) The line [self.nav popToRootViewControllerAnimated:NO] complains that it can't find the popToRootViewControllerAnimated: selector because my controller A actually sits below a TabBarController, which doesn't support that method. It seems that presentingViewController is returning that TabBarController. It probably works if A was the very first controller or was below a NavigationController, but not in my case unfortunately. – ZingMaster Dec 16 '12 at 22:47
  • @ZingMaster, then you can just redefine nav as [(UITabBarController *)self.presentingViewController viewControllers][0] (or whatever other number is appropriate for which index your navigation controller is at). – rdelmar Dec 16 '12 at 23:01
0

In iOS 6, if you use unwind segues, you don't get that curious effect. In your view controller that you want to jump back to, just define an unwind action:

- (IBAction)home:(UIStoryboardSegue *)segue
{
    // if you need to do any UI update because we got an unwind segue
    // back to this controller, do that here
}

Then in your presented view controller (and it can be multiple levels down) can do a unwind segue by dragging from the button that will initiate the segue down to the "exit" icon in the scene's dock. It will automatically go through, identify and presenting view controllers that have unwind actions, and present those choices.

The net effect is that you can jump back through multiple modals and navigation controllers, and you get only one animation effect.

Again, this is sadly iOS 6+ only.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks - yeah, I had read about these, but am reluctant to use them just yet. Prefer to have code that's compatible from iOS 5 onward. – ZingMaster Dec 16 '12 at 21:09
  • @ZingMaster Agreed. I've only recently decided to drop iOS 4 support (and largely because Apple forced our hand with Xcode 4.5), so I'm there with you... – Rob Dec 16 '12 at 21:14