Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

popToRootViewControllerAnimated does not display root view controller

I need a little help on a problem with navigation controllers.

I have a navigationController with 4 ViewControllers pushed. The last vc I push presents a further ViewController modally. The modal ViewController presents an ActionSheet. Depending on the user's answer I either dismiss the modal ViewController only or I want to go back to the root ViewController.

In the ViewController presented modally I have:

- (void) dismissGameReport
{    
    [[self delegate] GameReportModalWillBeDismissed:modalToPopToRoot];    
}

In the last ViewController pushed onto the navigationController stack I have:

- (void)GameReportModalWillBeDismissed: (BOOL)popToRoot;
{    
    if (popToRoot) 
        {
        [self.navigationController popToRootViewControllerAnimated:NO];
        }
    else 
        {
        [self dismissModalViewControllerAnimated:YES];
        }            
}

Dismissing the modal view controller works fine. However,

[self.navigationController popToRootViewControllerAnimated:NO];

does not cause the root ViewController to display its views. Adding some log info I see that after the message to self.navigationController the stack is correctly popped but execution continues sequentially. The screen still shows the view of the modal ViewController.

As a workaround I tried always dismissing the modal view controller and in the ViewWillAppear method have the popToRootAnimated message. No difference. Still the stack of controllers is popped but the screen continues showing my modal view controller's view and execution continues sequentially.

Could someone help me please?

like image 971
DanL Avatar asked Jan 18 '12 19:01

DanL


1 Answers

I like these deceptive questions. It seems very simple, until you try to do it.

What I found was that basically you do need to dismiss that modal view controller, but if you try to pop from the navigation controller on the next line things get mixed up. You must ensure the dismiss is complete before attempting the pop. In iOS 5 you can use dismissViewControllerAnimated:completion: like so.

-(void)GameReportModalWillBeDismissed:(BOOL)popToRoot{    
    if (popToRoot){
        [self dismissViewControllerAnimated:YES completion:^{
            [self.navigationController popToRootViewControllerAnimated:YES];
        }];
    }
    else{
        [self dismissModalViewControllerAnimated:YES];
    }            
}

But I see you have 4.0 in your question tags. The solution I found for <iOS 5 is far less pretty but should still work, and it sounds like you were already on the trail. You want viewDidAppear: not viewWillAppear:. My solution here involves an ivar, lets say:

BOOL shouldPopToRootOnAppear;

And then your GameReportModalWillBeDismissed: would look something like this:

-(void)GameReportModalWillBeDismissed:(BOOL)popToRoot{    
    shouldPopToRootOnAppear = popToRoot;
    [self dismissModalViewControllerAnimated:YES];          
}

And your viewDidAppear: would look like this...

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    if (shouldPopToRootOnAppear){
        [self.navigationController popToRootViewControllerAnimated:YES];
        return;
    }
    // Normal viewDidAppear: stuff here
}
like image 107
NJones Avatar answered Oct 12 '22 19:10

NJones