"From View Controller" disappears using UIViewControllerContextTransitioning

NiravPatel picture NiravPatel · Jun 21, 2014 · Viewed 31.9k times · Source

I got one problem and i have described it below.

I am using UIViewControllerContextTransitioning for custom transitions.

I have 2 view controllers, first view controller and second view controller.

Now I want to add second view controller on first view controller with an animation. I have achieved it, now the second view controller is transparent, so we can see first view controller below second view controller.

But I am not able to see first view controller, and I can see only black screen below second view controller.

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
    self.transitionContext = transitionContext;
    if(self.isPresenting){
        [self executePresentationAnimation:transitionContext];
    }
    else{
       [self executeDismissalAnimation:transitionContext];
    }
  }

-(void)executePresentationAnimation:(id<UIViewControllerContextTransitioning>)transitionContext{
     UIView* inView = [transitionContext containerView];
     UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

     UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

     CGRect offScreenFrame = inView.frame;
     offScreenFrame.origin.y = inView.frame.size.height;
     toViewController.view.frame = offScreenFrame;

    toViewController.view.backgroundColor = [UIColor clearColor];
    fromViewController.view.backgroundColor = [UIColor clearColor];
    inView.backgroundColor = [UIColor  clearColor];
    [inView insertSubview:toViewController.view aboveSubview:fromViewController.view];
     // [inView addSubview:toViewController.view];
    CFTimeInterval duration = self.presentationDuration;
    CFTimeInterval halfDuration = duration/2;

    CATransform3D t1 = [self firstTransform];
    CATransform3D t2 = [self secondTransformWithView:fromViewController.view];

    [UIView animateKeyframesWithDuration:halfDuration delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{

    [UIView addKeyframeWithRelativeStartTime:0.0f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t1;
    }];

    [UIView addKeyframeWithRelativeStartTime:0.5f relativeDuration:0.5f animations:^{
        fromViewController.view.layer.transform = t2;
    }];
    } completion:^(BOOL finished) {
    }];


    [UIView animateWithDuration:duration delay:(halfDuration - (0.3*halfDuration)) usingSpringWithDamping:0.7f initialSpringVelocity:6.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
        toViewController.view.frame = inView.frame;
    } completion:^(BOOL finished) {
        [self.transitionContext completeTransition:YES];
    }];
}

When [self.transitionContext completeTransition:YES]; called, suddenly the first view controller disappears and black screen displays below second view controller.

Does any one have idea ? Thanks.

Answer

Ash Furrow picture Ash Furrow · Jul 5, 2014

I was having the same problem here – looks like a bug in iOS 8. I've filed a radar.

I used Reveal to inspect the view hierarchy after the screen goes black. The key UIWindow is completely empty – no view hierarchy at all!

Reveal'd

I played around a bit and it looks like there is an easy workaround, for simple cases. You can just re-add the toViewController's view as a subview of the key window's:

transitionContext.completeTransition(true)
UIApplication.sharedApplication().keyWindow!.addSubview(toViewController.view)

I've checked and the key window's rootViewController is still correctly set, so that's fine. I'm not sure what would happen if you presented your controller from within an already presented modal controller, so for more complex cases, you'll have to experiment around.