views:

804

answers:

2

I'm having trouble popping a UIViewController off of a UINavigation controller even though the reference to the nav seems to be correct and a count on viewControllers shows the right number.

I have a UINavController that gets it's first UIViewController set and then the nav controller is presented in a modal view:

workoutNavController.viewControllers = [NSArray arrayWithObject:manageWorkoutController];
[self presentModalViewController:workoutNavController animated:YES];

That first UIViewController (manageWorkoutController) has a table view, and when one of the cells is touched a 2nd UIViewController is pushed onto the Navigation Controller:

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    switch (indexPath.row) {

        case 0:
            //do nothing no nav-view here
            break;

        //DIFFICULTY
        case 1:
            workoutDifficultyController.title = @"Workout Difficulty";
            [(UINavigationController *)self.parentViewController pushViewController:workoutDifficultyController 
                                                                           animated:YES];
            break;

        //DATE
        case 2:
            workoutDateController.title = @"Workout Date";
            [(UINavigationController *)self.parentViewController pushViewController:workoutDateController 
                                                                           animated:YES];
            break;

        default:
            break;

    }//end switch

}//end didSelectRowAtIndexPath

In the 2nd UIViewController (workoutDifficultyController) I'm setting up a Cancel and Save UIBarButtonItem in the viewDidLoad method, so that cancel button over-rides the default back button on the Nav Bar.

- (void)viewDidLoad {

    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelDifficulty:)];
    [self.navigationItem setLeftBarButtonItem:cancelButton];
    [cancelButton release];

    UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveDifficulty:)];
    [self.navigationItem setRightBarButtonItem:saveButton];
    [saveButton release];

    [super viewDidLoad];

}//end viewDidLoad

My problem is that in the cancelDifficulty method where I want to pop the current view off the nav controller and go back, I keep getting a 'EXEC_BAD_ACCESS' error. This is the method:

-(IBAction)cancelDifficulty:(id)sender {
    [(UINavigationController *)self.parentViewController popViewControllerAnimated:YES];
}//cancelDifficulty

I've tried method chaining back to the class that actually owns the navController, as well as using popToViewController:Animated:. If I use NSLog to print out the viewControllers count from the cancelDifficulty method it shows the right number but if I try to interact with it I either get the EXEC_BAD_ACCESS or nothing happens at all.

+2  A: 

Why aren't you just accessing the navigationController property of your view controller, rather than casting its parentViewController as a UINavigationController (which is a bad idea, regardless).

Ben Gottlieb
If I try with self.navigationController I get this error:-[CALayer retrieveValueForKey:]: unrecognized selector sent to instance 0x3b3b900Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[CALayer retrieveValueForKey:]: unrecognized selector sent to instance 0x3b3b900'
bwizzy
Also, If I completely remove my viewDidLoad method so the Nav controller should have it's out-of-the-box functionality, I still get EXEC_BAD_ACCESS when hitting the stock back button.
bwizzy
Try turning on NSZombies, and see if you're potentially pre-releasing an object. Also, it's not clear how you're setting up workoutNavController, but I would use pushViewController:animated:, rather than setting its viewControllers array.
Ben Gottlieb
I think NSZombies is leading in the right direction, initially it appears that the popViewControllerAnimated is working properly, but the viewWillAppear method of the view about to be shown is accessing an object that is no longer available. Thanks!
bwizzy
A: 

I would try the following and see if it works:

-(IBAction)cancelDifficulty:(id)sender {
    [(UINavigationController *)self.navigationController popViewControllerAnimated:YES];
}//cancelDifficulty

It could be that parentViewController isn't really a UINavigationController

macinjosh
Same thing happens, EXEC_BAD_ACCESS, If I log self.parentViewController it is a UINavigationViewController, and if I log a count on [self.parentViewController viewControllers] it shows 2 which is right.
bwizzy
Sometimes EXEC_BAD_ACCESS means you are attempting to access a something in memory that has been released. Double check that you aren't releasing any object that you need too early.
macinjosh
Seems like the EXEC_BAD_ACCESS is being thrown by the popViewControllerAnimated: method. See the comment above, if I don't override the bar button items and use stock functionality it still fails. NSLog(@"VCs: %@", [(UINavigationController *)self.parentViewController viewControllers]); Logs out this, so I'm not sure why I can't pop one: VCs: ( <ManageWorkoutViewController: 0x3b3d540>, <ManageWODiffController: 0x3b39690> )
bwizzy