Question

I have a view that requires user to be logged in. When the user attempts to open that view an he is not logged in I will call the login view for him to login and after he is done I will call the original view that he intended to see.
On iPhone this works fine as I push view controllers there. But on iPad where I present view controller this does not work. It says that dismissal in progress, can't show new controller. Here is the code:

- (void) buttonPressed
{
    if (!userLoggedIn) { // userLoggedIn getter calls new screens of login if needed
    return;  // this is executed if user declined to login
    }
    MyViewController *temp = [[MyViewController alloc] init];
    [self.navigationController presentViewController:temp animated:YES]; // this returns warning that dismissal in progress and does not work
}

What can I do about that? On iPhone all of my logic works fine, but on iPad it fails. I use it in many places and completely rewriting code is not good.

EDIT: more code:

- (BOOL) userLoggedIn {
   // code omitted
    [centerController presentViewController:navController animated:YES completion:nil];
   // code omitted
   [centerController dismissViewController:navController animated:YES]; // setting to NO does not fix my problem
   return YES;
}

EDIT2: This is the code for iPad. I have removed iPhone-related code. What it does on iPhone - instead of presenting controller it uses pushing, and in that situation everything works fine.

Was it helpful?

Solution

You cannot present another view as long as the dismissing of your 1st view is not complete. The animation of dismissing view should be completed before presenting new view. So, either you can set its animation to NO while dismissing, or use performSelector:withObject:afterDelay: and present the next view after 2-3 seconds.

Hope this helps.

OTHER TIPS

You've not posted enough code to really see what you're doing, but one approach to the problem of dismissing and pushing view controllers clashing in this way is to make a the pop+posh into a single atomic operation operation, rather then seqential operations.

You can do this by using the setViewControllers:animated: method on UINavigationController. This allows you to effectively remove one or more view controllers, and add one or more view controllers, all as one cohesive operation, with one seamless animation.

Here's a simple example:

[self.navigationController pushViewController:loginController];

// ... later on, when user login is validated:
NSMutableArray *viewControllers = 
    [self.navigationController.viewControllers copy];

[viewControllers removeLastObject];

[viewControllers addObject:[[MyNewViewController alloc] init]];

[self.navigationController setViewControllers:viewControllers animated:YES];

If you do things this way, your code will be more predictable, and will work across iPhone and iPad.

For more info, see the API docs.

Update

Since your problem involves a modal dialog on top, try using setViewControllers:animated:NO to change the nav controller stack underneath the modal login dialog before you dismiss the modal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top