0

I have a series of UIViewControllers in my app, and these are presented using a UINavigationController. The HOME ViewController calls pushViewController to get to the PROFILES ViewController. The PROFILES screen correctly shows the back button to HOME. Then selecting a button on PROFILES will take the user to the DETAIL ViewController. The DETAIL screen correctly shows the back button to PROFILES. But when I press the back button to PROFILES, I do indeed go back to the PROFILES screen but the navigation bar on that screen now shows the title HOME with no back button. In other words, it appears that IOS 8 has popped the ViewController once to go back from DETAIL to PROFILES, but has somehow popped the navigation bar items twice!

Any idea how I can fix this?

Marc
  • 3,386
  • 8
  • 44
  • 68
  • you may want to include which mechanisms you are using to push onto the navigation stack. Do you use a storyboard? Are you using segues? Are you using pushViewController:? Also, do your logs mention anything about a corrupt navigation stack? – atreat Oct 16 '14 at 20:39
  • I'm just using the old standard pushViewController. I don't use storyboard or segues. This is really basic IOS coding that works fine in older version of IOS and XCode but seems to be broken in IOS8 using XCode 6. – Marc Oct 16 '14 at 21:09
  • I'm glad I'm not the only one :-) See my solution below. – Marc Nov 26 '14 at 19:10

1 Answers1

0

Apparently the solution outline can be found here: UINavigationController and UINavigationBarDelegate.ShouldPopItem() with MonoTouch

In my solution, I just have all my view controllers extend CustomUINavigationController, which looks like this:

#import "CustomUINavigationController.h"
#import "IOSVersion.h"

@interface CustomUINavigationController ()

@end

@implementation CustomUINavigationController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.delegate=self;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//
// The following two methods are the key to overriding the buggy behavior in IOS 8
// The first method is from here:
// https://stackoverflow.com/questions/6413595/uinavigationcontroller-and-uinavigationbardelegate-shouldpopitem-with-monotouc
//
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
    NSLog(@"Inside shouldPopItem");
    if (regularPop) {
        NSLog(@"regularPop is TRUE");
    } else {
        NSLog(@"regularPop is FALSE");
    }
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        if (regularPop) {
            regularPop = FALSE;
            return YES;
        }

        regularPop = TRUE;
        [self popViewControllerAnimated:YES];
        return NO;
    } else {
        return [super navigationBar:navigationBar shouldPopItem:item];
    }
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    NSLog(@"Inside popViewControllerAnimated");
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
        int cnt=(int)[viewControllers count];
        NSLog(@"Inside popViewControllerAnimated, cnt is %d",cnt);
        UIViewController *vc=[viewControllers objectAtIndex:cnt-2];
        if (regularPop) self.desiredVC=vc;
        [self popToViewController:vc animated:animated];
        return vc;
    } else {
        return [super popViewControllerAnimated:animated];
    }

}

- (UIViewController *)manualpopViewControllerAnimated:(BOOL)animated {
    NSLog(@"Inside manualpopViewControllerAnimated");
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
        regularPop=TRUE;
        return [self popViewControllerAnimated:animated];
    } else {
        return [super popViewControllerAnimated:animated];
    }
}

- (void)navigationController:(UINavigationController *)navigationController
   didShowViewController:(UIViewController *)viewController
                animated:(BOOL)animated {
    NSLog(@"Inside didShowViewController");
    if (viewController==self.desiredVC) {
        NSLog(@"Inside didShowViewController, found desiredVC");
        regularPop = FALSE;
    }
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
Community
  • 1
  • 1
Marc
  • 3,386
  • 8
  • 44
  • 68
  • Hi Marc, what is "IOSVersion.h"? Is that another custom class of yours? – Sev Dec 11 '14 at 19:29
  • Yes that's just a file I use that has macros like SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0"). You can certainly infer from the name what they do. For example: #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending) – Marc Dec 12 '14 at 00:02