views:

72

answers:

1

I have 3 views.

I want to do the following:

A presents B modally
A dismisses B
A presents C modally

I have setup a delegate pattern where A is B's delegate. This is how I am presenting and dismissing in B:

[delegate dismissB]; //this is just [self dismissModalViewControllerAnimated:NO]
[delegate presentC]; //this is just [self presentModalViewController:c animated:NO];

For some reason my app crashes when I execute this code with no debugger results (I have NSZombieEnabled).

When I comment out [delegate presentC] the app will dismiss B properly. When I comment out [delegate dismissB] the app does nothing, even though the line executes. I am not sure why?

UPDATE: Here is the code in A

-(void)showARView{
    [self dismissModalViewControllerAnimated:NO];

    ARViewController* arViewController = [[[ARViewController alloc] initWithNibName:@"ARViewController" bundle:nil]autorelease];
    UINavigationController *arNavController = [[UINavigationController alloc] initWithRootViewController:arViewController];

    LeaderBoardTableViewController* lbViewController = [[[LeaderBoardTableViewController alloc] initWithNibName:@"LeaderBoardTableViewController" bundle:nil]autorelease];
    lbViewController.title = @"Leaderboard";    
    UINavigationController *lbNavController = [[UINavigationController alloc] initWithRootViewController:lbViewController];

    arTabBarController = [[UITabBarController alloc] init];//initWithNibName:nil bundle:nil];
    arTabBarController.delegate = self;
    arTabBarController.viewControllers = [NSArray arrayWithObjects:arNavController, lbNavController, nil];
    arTabBarController.selectedViewController = arNavController;

    [arNavController release];
    [lbNavController release];

    [self presentModalViewController:arTabBarController animated:NO];
}

Here is the code in B

[delegate showARView];
A: 

When you call dismissB the delegate dismisses the viewcontroller. Under normal circumstances (if you do not retain it elsewhere) this leads to the viewcontroller to be dealloced synchronously. And afterwards you are trying to access the delegate instancevariable, but for this the code needs a sane (hidden) self pointer, which is dealloced. I'm not sure if NSZombie can help in this case. You can easily find out if this is the reason for your crash, by inserting [[self retain] autorelease]; before [delegate dismissB];. However this is a hack and not a fix. You have a design problem.

This is not the way delegates are meant to be used. B presents some userinterface and receives some user interaction. It should then tell A what has happened via a delegate message, e.G. bWasCanceled or bFinished. It is the duty of the delegate, in your case A, to decide what to do next. So in your case the delegate may decide to dismiss B and instead present C. Or in code:

// Inside A
- (void)controllerB:(UIViewController*)ctl didFinishWithResult:(id)something {
    [self dismissModalViewControllerAnimated:NO];
    // Instantiate and initialize c
    [self presentModalViewController:c animated:NO];
}

// Inside B
[delegate controllerB:self didFinishWithResult:@"OK"];

If I completely misinterpreted your code, and everything is fine there, I have an other suggestion. I have seen strange issues when dismissing and presenting modal viewcontrollers in the same round of the runloop. You may try [delegate performSelector:@selector(presentC) withObject:nil afterDelay:0.0]; and see if that helps.

tonklon
Thanks for the detailed explanation. I have updated my code in this post, but still get the same results. Even the hackish retain message didn't work. Thoughts?
Sheehan Alam