9

In iOS 7, we do a custom animation transitioning into a new view controller, with the completion of the animation being:

[self.animatedView removeFromSuperview]; //superview == self.view, in this case
[self presentViewController:newController animated:NO completion:nil];

This works fine in <= IOS 7. We also do it while animating back to the original, with dismissViewController:. However, in iOS 8, both present and dismiss display a one frame black screen between the end of the animation and the appearance of the new view. Is there a way around this? Everything is already happening on the main thread.

modusCell
  • 13,151
  • 9
  • 53
  • 80
puzzl
  • 833
  • 9
  • 19
  • I'm having the same issue. Did you find a solution other than @tdevoy's suggestion to use `UIViewControllerAnimatedTransitioning`? – scttnlsn Sep 15 '14 at 21:04
  • Nope, I ended up using the animated transition, which added 70 lines of code despite doing the exact same thing, performs slower, and presents other issues. That's what you get for using Apple's libraries. – puzzl Sep 16 '14 at 01:02
  • iOS 8 offers UIPresentationController for such stuff. – pronebird Sep 23 '14 at 12:22

3 Answers3

0

Really got to suggest you should just adopt the UIViewControllerAnimatedTransitioning protocol for iOS 7 and above. It's easy to work with, and incredibly optimized for doing any transition type and length. By all means, continue using your own animations for ios 6 and below, but your animations with improve by leaps and bounds if you adopt the new protocol for ios 7 and above.

Check out the docs on UIViewControllerAnimatedTransitioning

Tommy Devoy
  • 13,441
  • 3
  • 48
  • 75
  • You forgot to mention, it's incredibly buggy too, but that's the only way anyway. – pronebird Sep 23 '14 at 12:19
  • I haven't seen any problems. What's the bug you're experiencing? – Tommy Devoy Sep 23 '14 at 15:54
  • you probably would love to read the source of my modal transition I wrote for iOS 7 and later fixed for iOS 8. https://github.com/pronebird/CustomModalTransition/blob/master/CustomModalTransition/ModalTransitionAnimator.m – pronebird Sep 23 '14 at 16:25
  • The most important: rotations are broken on iOS 7. I am not sure it solved either on iOS 8. – pronebird Sep 23 '14 at 16:26
  • The best on iOS 8 is to use UIPresentationController. Then you can handle rotations and everything. But that's something missing on iOS 7. – pronebird Sep 23 '14 at 16:39
  • Oh wow that's interesting about the rotations. Thanks for the tip! – Tommy Devoy Sep 23 '14 at 16:42
0

I have the same issue and my fix was getting these two classes.

http://www.brightec.co.uk/blog/ios-7-custom-view-controller-transitions-and-rotation-making-it-all-work

Easy just import them into the project and set the transition delegate:

BTSlideInteractor *interactor = [[BTSlideInteractor alloc] init];
interactor.presenting = YES;

UIStoryboard *storyboard = self.storyboard;
ViewController *svc = [storyboard instantiateViewControllerWithIdentifier:@"home"];
svc.modalPresentationStyle = UIModalPresentationCustom;
svc.transitioningDelegate = interactor;
[self presentViewController:svc animated:YES completion:nil];

You can customise the transition from the delegate classes. Regards

Viktor Todorov
  • 380
  • 3
  • 15
0

I was still experiencing this on iOS 9. As others mentioned, it seems the only way to avoid it is to create an object implementing UIViewControllerAnimatedTransitioning. Hopefully I can save someone else the time in navigating this poorly documented API. Here's what you need to do:

  1. Set self.modalPresentationStyle = UIModalPresentationCustom; in the VC to be presented.
  2. In the presenting VC, implement UIViewControllerTransitioningDelegate and do something like this:

    UIViewController* myVC = [[UIViewController alloc] init];
    myVC.transitioningDelegate = self;
    [self presentViewController:myVC animated:YES completion:nil];
    
  3. Return your custom animator object in the presenting VC.

    - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
        return [[MXQuickFadeTransition alloc] init];
    }
    
    - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
        MXQuickFadeTransition* transition = [[MXQuickFadeTransition alloc] init];
        transition.duration = 0.3f;
        return transition;
    }
    
  4. Implement that transition like so:

    @implementation MXQuickFadeTransition
    
    - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext {
        return self.duration > 0 ? self.duration : 0.01f;
    }
    
    - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
        UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIView *containerView = transitionContext.containerView;
    
        const BOOL isPresenting = [toController presentedViewController] != fromController;
    
        if (isPresenting) {
            [containerView addSubview:toController.view];
            [containerView bringSubviewToFront:toController.view];
        }
    
        fromController.view.alpha = 1.0f;
        toController.view.alpha = 0.0f;
        [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
            fromController.view.alpha = 0.0f;
            toController.view.alpha = 1.0f;
        } completion:^(BOOL finished) {
            [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
        }];
    }
    
    @end
    

Useful references:

Community
  • 1
  • 1
skensell
  • 1,421
  • 12
  • 21