33
votes

I compile my project using Xcode6 GM on iOS8 GM. When dismissing many view controllers, my app always crashes and the debug area shows:

"Trying to dismiss the presentation controller while transitioning already. transitionViewForCurrentTransition is not set, presentation controller was dismissed during the presentation? "

I have googled and find a similar case and shows the same error:

[self.viewController presentViewController:vc animated:NO completion:^{
        [self.viewController dismissViewControllerAnimated:NO completion:nil];
}];

It works fine using Xcode5 and iOS7 . What does the error means? Is iOS8 isn't happy with the "Hack"? Thanks in advance.

4
What are you trying to achieve by above code ?Midhun MP
I just ran into the exact same error..Jeef
My assumption this is forcing a view into a single orientation - Thats what i'm doing and i have the same errorJeef
When dismissing many view controllers, if I dismiss them from front to back, my app crashes, but in the opposite order(from back to front), my app works fine..ylovesy

4 Answers

38
votes

Are you trying to force a device orientation change? Anyway, in my opinion you could try to change your current code to:

[self.navigationController presentViewController:vc animated:NO completion:^{
    dispatch_after(0, dispatch_get_main_queue(), ^{
        [self.navigationController dismissViewControllerAnimated:NO completion:nil];
    });
}];
9
votes

I had the same issue and I found a clean solution avoid using dispatch_async or dispatch_after.

Simply, as described by the exception, you are trying to dismiss a view controller while the presenting transition is still in progress. This means that once the

- presentViewController:animated:completion: 

completion block is called, and you invoke the dismiss, the transitioning is not completed.

Starting from iOS 7 transitioning UIViewController has a new method available

- transitionCoordinator 

The transitionCoordinator gives you the chance to enqueue a completion block as soon as the transition completes.

The object returned by the method conforms the UIViewControllerTransitionCoordinator protocol. Knowing that the solution is really simple.

After the invocation of

- presentViewController:animated:completion: 

the transition coordinator is properly configured by the framework.

Use

- animateAlongsideTransition:completion: 

on it to send the proper completion block.

Here a little code snippet that better explain the solution

void(^completion)() = ^() {
    [modalViewController dismissViewControllerAnimated:YES completion:nil];
};

// This check is needed if you need to support iOS version older than 7.0
BOOL canUseTransitionCoordinator = [viewController respondsToSelector:@selector(transitionCoordinator)];

if (animated && canUseTransitionCoordinator)
{
    [viewController presentViewController:modalViewController animated:animated completion:nil];
    [viewController.transitionCoordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        completion();
    }];
}
else
{
    [viewController presentViewController:modalViewController animated:animated completion:completion];
}
1
votes

My solution:

dismissViewControllerAnimated:completion:If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack.

For example,I have 4 views:A->B->C->D and when I want to dismiss B, I firstly check if C also want to dismiss by using objc_setAssociatedObject to attach/detach a NSString object, and if C wants to dismiss too,then just cancel C's request.Just call dismiss to B.

-2
votes
ThirdViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Third"];
UIViewController *VC1 = self.presentingViewController;
[self dismissViewControllerAnimated:NO completion:^{}];
[VC1 presentViewController:vc animated:YES completion:^{}];