Search code examples
iosios7core-animation

How to use animateWithDuration: when presenting view controller on iOS 7?


I'm currently using the following code in order to present my view controller.

CATransition* transition = [CATransition animation];
transition.duration = 1;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromBottom;
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:viewController animated:NO completion:nil];

I need to use more complex animation utilizing UIView animateWithDuration method. It is just modal presentation and background view controller should stay there. How can I animate presenting view controller's view?

Update: next version of code :)

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:NULL];
RootViewControllerEx *viewController = (RootViewControllerEx *)[sb instantiateViewControllerWithIdentifier:@"SB_RDVC"];
viewController.transitioningDelegate = self;
viewController.modalPresentationStyle = UIModalPresentationCustom;
[self presentViewController:viewController animated:YES completion:nil];
...

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    ...
}

VC in storyboard doesn't have any segue specified, it stays lonely in storyboard :)


Solution

  • You need to use UIModalPresentationCustom as your UIViewController's modalPresentationStyle.

    You then need to create a class that conforms to the UIViewControllerTransitioningDelegate and set that your on presentedViewController.

    Example

    YourViewController *viewController = [[YourViewController alloc] init];
    viewController.delegate = self;
    viewController.transitioningDelegate = self;
    viewController.modalPresentationStyle = UIModalPresentationCustom;
    
    [self.navigationController presentViewController:viewController animated:YES completion:nil];
    

    You must then implement the following method:

    - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;
    

    Which returns an object that conforms to a UIViewControllerAnimatedTransitioning protocol, that implements the following method:

    - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIView *inView = [transitionContext containerView];
        UIView *toView = [[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey] view];
    
        toView.frame = //CGRectMake(0,0,0,0);
        [inView addSubview:toView];
        // Use whatever animateWithDuration you need
        [UIView animateWithDuration:0.6f delay:0.0f usingSpringWithDamping:0.7f initialSpringVelocity:0.5f options:UIViewAnimationOptionCurveEaseIn animations:^{
    // Custom animation here
        } completion:^(BOOL finished) {
            // IMPORTANT
            [transitionContext completeTransition:YES];
        }];
    }
    

    Always remember to tell the context when a transition is complete, otherwise you'll enter an unstable state.