6
votes

iOS documentation for dismissViewControllerAnimated:completion: states:

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. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.

This means when dismissing two modal view controllers at once using

[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];

the animation shown should be the top modal view being dismissed.

This is indeed the case in iOS 7 and prior, but in iOS 8 the animation shown is not the top-most view (in my experience, it's the second top-most view). Is this behavior a bug in iOS 8 or am I doing something wrong?

2
Do you mean the top most view suddenly disappear at the beginning of the animation ?Tancrede Chazallet
I'm pretty sure this is a bug. It also happens if you do an unwind segue that goes back multiple controllers ( if I remember correctly, in that case, you do see the top view disappearing, but also briefly, the second to last controller).rdelmar
Has a bug report been filed to Apple? I don't know how to do that or how to check.James
I see the exact same issue in an unwind segue context. Help would be great.theguy

2 Answers

3
votes

As commented above: I see the exact same issue in an unwind segue context. I just toke the workaround as described here using a screenshot and add it as a subview to all intermediate viewControllers: How to dismiss a stack of modal view controllers with animation without flashing on screen any of the presented VCs between the top and bottom?

    // this in during unwind in a custom UIStoryboardSegue (that is the reason why it might look wrong with what is what: srcViewController and destViewController
    UIViewController* aPresentedViewController = destViewController.presentedViewController;
    while (aPresentedViewController != nil) {
        if (aPresentedViewController == srcViewController) {
            break;
        }
        UIView *anotherSrcViewCopy = [srcViewController.view snapshotViewAfterScreenUpdates: NO];
        anotherSrcViewCopy.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        [aPresentedViewController.view addSubview:anotherSrcViewCopy];
        // recurse through the presentedViewController hierarchy
        aPresentedViewController = aPresentedViewController.presentedViewController;
    }
1
votes

Same problem and same solution here than @theguy. Here's my version in Swift without iterating on all the view controllers :

guard
    let presentedViewController = segue.destination.presentedViewController,
    let viewToCopy              = segue.source.view.snapshotView(afterScreenUpdates: false)
else { return }

viewToCopy.autoresizingMask = [.flexibleWidth, .flexibleHeight]
presentedViewController.view.addSubview(viewToCopy)