Calling popToRootViewControllerAnimated causing crash. How should I be doing this?

Posted by Lewis42 on Stack Overflow See other posts from Stack Overflow or by Lewis42
Published on 2012-11-12T09:35:46Z Indexed on 2012/11/14 5:00 UTC
Read the original article Hit count: 168

The app is for taking body measurements. The user can say I want to measure: legs, arms and neck, in the settings tab and in the main tab there is a view which loops round to take each measurement.
This is achieved like so:

i have tab controller the first tab has a navigation controller the first view controller on the storyboard and has one segue to itself the board loops round until it has all the measurements then it segues to a different controller

the problem is: if the user changes which measurements they are taking in the settings tab, the first tab needs to completely reload, as if the app was just starting up, clearing down the whole nav stack etc.

at the moment the tab controller calls popToRootViewControllerAnimated on the navigation controller in the measurements tab, but this is causing a crash. Each screen has a slider control and a call to titleForRow:forComponent: is being called on a deleted view causing it to crash.

What am I doing wrong?!

Here's the tab bar controller code

//  TabBarController.m
//

#import "TabBarController.h"
#import "TodaysMeasurementObject.h"
#import "AppDelegateProtocol.h"
#import "AddMeasurementViewController.h"
#import "ReadPerson.h"
#import "AppDelegate.h"

@interface TabBarController () <UITabBarControllerDelegate>



@end

@implementation TabBarController

bool resetWizardView = false;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

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

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:)
                                                 name:UIDeviceOrientationDidChangeNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(measurementsSettingsUpdated:) name:@"MeasurementsSettingsUpdated" object:nil];

}

- (void) measurementsSettingsUpdated:(NSNotification *) notification
{
//    UINavigationController *navigationController = [self.viewControllers objectAtIndex:0];
//    AddMeasurementViewController *addMeasurement = [[AddMeasurementViewController alloc] init];
//    [navigationController setViewControllers: [[NSArray alloc] initWithObjects:addMeasurement, nil]];
    resetWizardView = YES;
}

- (void) viewDidAppear:(BOOL)animated
{
    if (![ReadPerson userHasRecords]) {
        [self setSelectedIndex:3];
    }
}

- (void)orientationChanged:(NSNotification *)notification
{
    // We must add a delay here, otherwise we'll swap in the new view
    // too quickly and we'll get an animation glitch
    [self performSelector:@selector(showGraphs) withObject:nil afterDelay:0];
}

- (void)showGraphs
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (deviceOrientation == UIDeviceOrientationLandscapeLeft && !isShowingLandscapeView)
    {
        [self performSegueWithIdentifier: @"toGraph" sender: self];
        isShowingLandscapeView = YES;
    }

    else if (deviceOrientation != UIDeviceOrientationLandscapeLeft && isShowingLandscapeView)
    {
        [self dismissModalViewControllerAnimated:YES];
        isShowingLandscapeView = NO;
    }
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if(interfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
        [self performSegueWithIdentifier: @"toGraph" sender: self];
    }

    return false;
}

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    int tbi = tabBarController.selectedIndex;
    if (tbi == 0) {
        [[viewController view] setNeedsDisplay];
        if (resetWizardView) {
            [(UINavigationController*)[self.viewControllers objectAtIndex:0] popToRootViewControllerAnimated: NO]; // ******* POP CALLED HERE ******
            resetWizardView = false;
        }
    }
}

- (TodaysMeasurementObject*) theAppDataObject
{
    id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
    TodaysMeasurementObject* theDataObject;
    theDataObject = (TodaysMeasurementObject*) theDelegate.theAppDataObject;
    return theDataObject;
}

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}


@end

UPDATED

- (void) measurementsSettingsUpdated:(NSNotification *) notification
{
    NSMutableArray *viewControllers = [[NSMutableArray alloc] initWithArray: self.viewControllers];
    UINavigationController *navigationController = [viewControllers objectAtIndex:0];
    AddMeasurementViewController *addMeasurement = [[AddMeasurementViewController alloc] init];
    [navigationController setViewControllers: [[NSArray alloc] initWithObjects:addMeasurement, nil]];

    [viewControllers setObject:navigationController atIndexedSubscript:0];

    self.viewControllers = viewControllers;
}

and removed the code from - tabBarController:didSelectViewController:

but still the same error. I think the problem is that it's trying to get a value for the slide control after the view has been deleted. But some part of the view must still be alive...? Anyway to kill that off? Or leave it all alive??

© Stack Overflow or respective owner

Related posts about objective-c

Related posts about ios