Wait with execution of viewWillDisappear until custom animation has completed?

1.5k Views Asked by At

I'd like to perform an animation when the user taps on the back button to segue back to my Root View Controller. The animation will simply highlight the changes that the user made in the detail view controller.

I tried this. The animation itself works (and is not really essential to my question, just left it in to illustrate what I'm doing.) The problem is that the segueing happens too fast and you can't see the animation.

How can I wait with the execution of viewWillDisappear until the animation has completed?

override func viewWillDisappear(animated: Bool) {
        // ...

        // Animate if text changes. reminderAfterRulesRun is a custom data structure. reminderNameTextInput is my outlet to my label
        if reminderNameTextInput.text != reminderAfterRulesRun.title {

            let originalreminderNameTextInputColor = self.reminderNameTextInput.textColor

            // Animate the removing of "All" and replacing it with the most commonly used list.
            UIView.animateWithDuration(0.3, delay: 0, options: .Autoreverse, animations: {

                // Fade out
                self.reminderNameTextInput.textColor = UIColor.redColor()
                self.reminderNameTextInput.text = reminderAfterRulesRun.title
                self.reminderNameTextInput.alpha = 0.0

                }, completion: {
                    (finished: Bool) -> Void in

                    // Once the label is completely invisible, set the text and fade it back in
                    UIView.animateWithDuration(0.3, delay: 0, options: .Autoreverse, animations: {
                        //                        self.reminderNameTextInput.selectedSegmentIndex = self.toSegmentedControlValue(reminderAfterRulesRun.reminderNameTextInput)!
                        self.reminderNameTextInput.text = reminderAfterRulesRun.title
                        self.reminderNameTextInput.textColor = originalreminderNameTextInputColor
                        self.reminderNameTextInput.alpha = 1.0
                        }, completion: nil)         
            })
        }
}
1

There are 1 best solutions below

4
On

Looks like you'll want to use the View Controller Transition API. At a high level you will need to implement the UINavigationControllerDelegate protocol methods in your View Controller. When you set your View Controller as the delegate of your Nav Controller and a transition is about to happen, this method is called. Here you can check and see what View Controllers are involved in the interaction and which direction the transition is going (Push or Pop). With this info you can provide the appropriate animator.

- (id<UIViewControllerAnimatedTransitioning>)
               navigationController:(UINavigationController *)navigationController
    animationControllerForOperation:(UINavigationControllerOperation)operation
                 fromViewController:(UIViewController*)fromVC
                   toViewController:(UIViewController*)toVC
{
if (operation == UINavigationControllerOperationPush) {
    return self.animator;
}
    return nil;
}

The "animator" is a NSObject subclass that implements the UIViewControllerAnimatedTransitioning protocol. This protocol has methods that ask for the time of the transition

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 0.25;
}

and then a call for implementing the transition:

- (void)animateTransition:    (id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.alpha = 0;

[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
    fromViewController.view.transform = CGAffineTransformMakeScale(0.1, 0.1);
    toViewController.view.alpha = 1;
} completion:^(BOOL finished) {
    fromViewController.view.transform = CGAffineTransformIdentity;
    [transitionContext completeTransition:![transitionContext transitionWasCancelled]];

}];

}