0

I have a UINavigationController ans a chain of 3 simple controllers. Each one has a button. When press a button a next controller is Pushed. ViewController1 -> ViewController2 -> ViewController3. When I push a back button on the 3rd view i want to move to the first view. Using of backBarButtonItem is obligatory. Here is the code for second controller:

#import "ViewController2.h"

static BOOL isBackButtonPressed;

@implementation ViewController2

- (void)viewDidLoad {
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"back from 3" style:UIBarButtonItemStyleBordered target:nil action:nil];
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated {
    if (isBackButtonPressed) {
        [self.navigationController popViewControllerAnimated:YES];
    } else {
        isBackButtonPressed = YES;
    }
    [super viewWillAppear:animated];
}

@end

But when I press back button on the third view I return to the second view instead of the first view. Could you help me to return to the first view pressing back button on the third view. I tried suggestions from answers but they don't help.

  1. Adding a selector to backBarButtonItem doesn't help because it is never called.
  2. Adding a [self.navigationController popToRootViewControllerAnimated:YES] in viewWillDisappear methos also doesn't work. I don't know why. I think that the actual problem is how backBarButtonItem works. Any other suggestions?

The behaviour I try to achieve exists in the calendar on iPhone. When you rotate iPhone to landscape you get to the weeek view. Then go to the event details, and rotate to the portrait. When you press back button you will get to a day view not to a week view, so a controller with weekview is skipped.

Cœur
  • 37,241
  • 25
  • 195
  • 267
PSsam
  • 639
  • 7
  • 18

4 Answers4

0

I had the same problem as you beofre and fixed it like this:

You can capture the back button on the ViewController3 and before poping the view, remove ViewController2 from the navigation stack like this:

- (void)viewDidLoad {
   [super viewDidLoad];
   self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"back from 3" style:UIBarButtonItemStyleBordered target:self action:@selector(customBackPressed:)];
}

-(void)customBackPressed:(id)sender {
        NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: navigationController.viewControllers];
        for (UIViewController *vc in viewControllers)
        {
        // If vc is ViewController2 type, remove it
        }

        navigationController.viewControllers = allViewControllers;

       [self.navigationController popViewControllerAnimated:YES];
 }

Because ViewController2 is not in the stack anymore, it will jump to ViewController1.

Also, if ViewController1 is the root view controller, you can just do:

[self.navigationController popToRootViewControllerAnimated:YES]; 
Antonio MG
  • 20,382
  • 3
  • 43
  • 62
  • This will get very complex when have more then three levels, also view 1 is the rootviewcontroller so why not just pop to the rootviewcontroller. – rckoenes Oct 07 '13 at 14:54
  • Thanx for your reply. Maybe I do something wrong, but when I use your code selector is not called. – PSsam Oct 07 '13 at 14:54
  • Try self.navigationItem.leftBarButtonItem instead – Antonio MG Oct 07 '13 at 14:56
  • I cant't because of design in my app. – PSsam Oct 07 '13 at 15:06
  • then your problem is different, you may post it in another question why your back button is not working, but once you can capture the back button, my answer works – Antonio MG Oct 07 '13 at 15:07
  • My aim is to find out how to pop a controlelr after back button is pressed. As is discussed [hear](http://www.cocoabuilder.com/archive/cocoa/297620-overriding-target-and-action-of-backbarbuttonitem.html) we can't use selector for backButton so it's not a solution.You are not right suggesting me idle code and saying that I should find out how to get your code working. – PSsam Oct 08 '13 at 06:28
  • What about removing VC2 with the method I showed you in the viewDidLoad of VC3? Then when you press back, VC2 is not in the stack and it goes to VC1 – Antonio MG Oct 08 '13 at 07:48
  • Back button returns to the VC2 even if it is removed from navigation stack. Back button does some real shit. – PSsam Oct 08 '13 at 08:16
  • That is incredibly weird, are you sure VC2 is removed from the stack correctly? Print navigationController.viewControllers in some moment to see if it stills there – Antonio MG Oct 08 '13 at 08:17
  • Yes. I really tried it. I achieved a result only removing a view controller from the stack in ViewDidDisappear event in VC3. But in this case i see VC2 first and then move to the VC1. – PSsam Oct 08 '13 at 08:22
  • And in the viewWillDissapear? – Antonio MG Oct 08 '13 at 08:27
  • It returns to the VC2. – PSsam Oct 08 '13 at 08:34
0

No need to register a new selector for the back button, just do:

-(void)viewWillDisappear{
    if ( [self.navigationController.viewControllers containsObject:self] )
         //It means that the view controller was popped (back button pressed or whatever)
         //so we'll just pop one more view controller
         [self.navigationController popViewControllerAnimated:NO];
}

in your ViewController3 viewWillDisappear method

micantox
  • 5,446
  • 2
  • 23
  • 27
0

Try using this in your third view controller, this way you check if you have pressed the back button and directly pop to the root view controller which as you stated is your first view controller.

-(void) viewWillDisappear:(BOOL)animated {
    if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) {
        [self.navigationController popToRootViewControllerAnimated:YES];
    }
    [super viewWillDisappear:animated];
}
ivan_yorgov
  • 1,281
  • 1
  • 9
  • 7
0

After countless number of tries my solution was simply not use backBarButtonItem! As whatever i do it always goes to previous viewController instead of calling its selector

Instead I use only leftBarButtonItem for navigation, as it guarantees calling my action.

Here an example

UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 27, 22)];
[backButton setImage:[UIImage imageNamed:@"backbutton"] forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(backButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

  self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

This certainly calls backButtonPressed action.. This works both for IOS 6 and 7

Gorkem
  • 701
  • 8
  • 22
  • Thank you for a reply. Some time has passed from this question and I do not remember details, but for some reasons I wanted to use exactly a back Button. I'm not going to check your solution but I believe it would work. – PSsam Sep 15 '14 at 13:18
  • No problem, since I already tried many hours searching for this solution, i think it should be here for others with similar problems – Gorkem Sep 17 '14 at 06:35