0

I have a UINavigationController with 4 items:

(root)mainvc -> callerlistvc -> addcallerformvc -> verifycallervc (in that specific order)

When I am on the verifycallervc screen, if I press back, I want to go back to callerlistvc.

Here is the catch however, the back button should be a system button.. So.. as far as I know I cannot replace the action with a selector calling poptoviewcontroller:animated (only works on a custom uibarbuttonitem)

So then I thought of manipulating the stack (pretty interesting and challenging too!) So here is what I did...

So currently Im on the verifycallervc screen... and this gets called.

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

NSMutableArray *allViewControllers = [self.navigationController.viewControllers mutableCopy];

__block UIViewController *mainvc = nil;
__block UIViewController *callerlistvc = nil;
__block UIViewController *addcallerformvc = nil;

[allViewControllers enumerateObjectsUsingBlock:^(UIViewController *vc, NSUInteger idx, BOOL *stop) {
    if ([vc isKindOfClass:[MainVC class]]) {
        mainvc = vc;
    } else if ([vc isKindOfClass:[CallerListVC class]]) {
        callerlistvc = vc;
    } else if ([vc isKindOfClass:[AddCallerFormVC class]]) {
        addcallerformvc = vc;
    }
}];

[self.navigationController setViewControllers:@[ mainvc, callerlistvc, self]];
}

After I did that, I pressed back normally and was now on the callerlistvc... great. Unfortunately when I press the button (push-segued to addcallerformvc)... it results in a crash EXC_BAD_ACCESS.

I also tried a different approach by first manipulating the variable callerlistvc like so before adding it in the setViewControllers method

callerlistvc = [[UIStoryboard storyboardWithName:@"main" bundle:nil] instantiateViewControllerWithIdentifier:@"CallerListVC"];

But the result is the same.

I have added breakpoints and it goes like this...

CallerListVC:

  1. tappedShowAddCallerListButton
  2. performSegueWithIdentifier
  3. prepareForSegue // identifier string is correct, destinationVC is not nil

then AddCallerFormVC: 4. viewDidLoad 5. viewWillAppear // properties not nil

after that EXC_BAD_ACCESS occurs

How can I make this work?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
daryl
  • 241
  • 1
  • 3
  • 13
  • 2 alternative approaches to changing the standard back button behaviour: 1 is to implement the UINavigationControllerDelegate method navigationController: willShowViewController: animated: and keep track of when you're popping from verifycallervc and simply pop again. OR look at the answer to this Q http://stackoverflow.com/questions/1214965/setting-action-for-back-button-in-navigation-controller – Michael Behan Feb 06 '14 at 15:21

2 Answers2

0

The better approach in this case would be to use a custom UINavigationController class and extend the popViewControllerAnimated: method. In this method either call the super method or pop to the specific view controller (super class method) based on a check. That way you have your system nav buttons and also control where the tack should pop to.

Kedar
  • 1,298
  • 10
  • 20
0

Don't override anything in verifycallervc and instead do following with normal back on verifycallervc

Override viewWillAppear or viewDidAppear for addcallerformvc like this

- (void)viewDidAppear:(BOOL)animated
{
   if (![self isBeingPresented]) {
      [self.navigationController popViewControllerAnimated:YES];
   }
}

Reference : https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/RespondingtoDisplay-Notifications/RespondingtoDisplay-Notifications.html#//apple_ref/doc/uid/TP40007457-CH12-SW7

Note: not tested, don't have XCode right now....

Piyuesh
  • 1,066
  • 1
  • 9
  • 18