5
votes

I've looked around for an answer for this and spent the last two hours pulling my hair out to no end.

I'm implementing a very basic custom view controller transition animation, which simply zooms in on the presenting view controller and grows in the presented view controller. It adds a fade effect (0 to 1 alpha and visa versa).

It works fine when presenting the view controller, however when dismissing, it brings the presenting view controller back in all the way to fill the screen, but then it inexplicably disappears. I'm not doing anything after these animations to alter the alpha or the hidden values, it's pretty much a fresh project. I've been developing iOS applications for 3 years so I suspect this may be a bug, unless someone can find out where I'm going wrong.

class FadeAndGrowAnimationController : NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
func animationControllerForPresentedController(presented: UIViewController!, presentingController presenting: UIViewController!, sourceController source: UIViewController!) -> UIViewControllerAnimatedTransitioning! {
    return self
}

func animationControllerForDismissedController(dismissed: UIViewController!) -> UIViewControllerAnimatedTransitioning! {
    return self
}

func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval {
    return 2
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning!) {
    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as UIViewController
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as UIViewController

    toViewController.view.transform = CGAffineTransformMakeScale(0.5, 0.5)
    toViewController.view.alpha = 0

    transitionContext.containerView().addSubview(fromViewController.view)
    transitionContext.containerView().addSubview(toViewController.view)
    transitionContext.containerView().bringSubviewToFront(toViewController.view)

    UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: {
        fromViewController.view.transform = CGAffineTransformScale(fromViewController.view.transform, 2, 2)
        fromViewController.view.alpha = 1

        toViewController.view.transform = CGAffineTransformMakeScale(1, 1)
        toViewController.view.alpha = 1
    }, completion: { finished in
        transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
    })
}

}

And the code to present:

    let targetViewController = self.storyboard.instantiateViewControllerWithIdentifier("Level1ViewController") as Level1ViewController
    let td = FadeAndGrowAnimationController()

    targetViewController.transitioningDelegate = td
    targetViewController.modalPresentationStyle = .Custom

    self.presentViewController(targetViewController, animated: true, completion: nil)

As you can see, a fairly basic animation. Am I missing something here? Like I said, it presents perfectly fine, then dismisses 99.99% perfectly fine, yet the view controller underneath after the dismissal is inexplicably removed. The iPad shows a blank screen - totally black - after this happens.

3
Are you using Xcode 6? Because I am experiencing the same error, and it worked for me on Xcode 5.Siegfoult

3 Answers

6
votes

This seems to be an iOS8 bug. I found a solution but it is ghetto. After the transition when a view should be on-screen but isn't, it needs to be added back to the window like this:

BOOL canceled = [transitionContext transitionWasCancelled];
[transitionContext completeTransition:!canceled];
if (!canceled)
    {
    [[UIApplication sharedApplication].keyWindow addSubview: toViewController.view];
    }

You might need to play around with which view you add back to the window, whether to do it in canceled or !canceled, and perhaps making sure to only do it on dismissal and not presentation.

Sources: Container view disappearing on completeTransition: http://joystate.wordpress.com/2014/09/02/ios8-and-custom-uiviewcontrollers-transitions/

2
votes

had the same problem ios 8.1

my swift code after completeTransition

if let window = UIApplication.sharedApplication().keyWindow {
    if let viewController = window.rootViewController {
        window.addSubview(viewController.view)
    }
}
2
votes

I was having the same problem when dismissing a content view controller. My app has this parent view controller showing a child view controller. then when a subview in the child is tapped, it shows another vc (which I am calling the content vc)

My problem is that, when dismissing the contentVC, it should go to child VC but as soon as my custom transition finishes, childVC suddenly disappears, showing the parent VC instead.

What I did to solve this issue is to

  1. change the .modalPresentationStyle of the childVC presented by parentVC from the default .automatic to .fullscreen.
  2. Then changed the .modalPresentationStyle of contentVC to .fullscreen as well.

This solves the issue. but it won't show your child VC as a card sheet (when using .overCurrentContext or automatic) which is new in iOS 13.