0

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)         
            })
        }
}
Daniel
  • 3,758
  • 3
  • 22
  • 43
  • I don't think viewWillDisappear is the right place to do this. I think you should consider building another function for the animation, and segue when you want.. (after the animation finishes) – William GP May 25 '16 at 02:58
  • @William GP But I'd like the animation to happen when the user segues back to the root view controller. So, how do I do that? – Daniel May 25 '16 at 03:02
  • Where is your segue currently? How is it triggered? – William GP May 25 '16 at 03:03
  • @William GP I'm segueing back from my detail view controller to my root view controller by pressing the back button on the top left. – Daniel May 25 '16 at 03:07
  • Using a storyboard? I would put the above code in the function for that back button, and then `prepareForSegue` at the end of the function, after the animations have finished – William GP May 25 '16 at 05:45
  • @William GP I have a root view controller from which I have in storyboard (IB) a "Show" storyboard segue to the Detail View Controller. Hence, I didn't have to create the "back" button on the top left (in the table view's title bar), it was created for me automatically. So, I don't have a function for this back button. – Daniel May 25 '16 at 05:51

1 Answers1

1

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]];

}];

}
Richmond Watkins
  • 1,342
  • 9
  • 17
  • Thanks, I'll try this. However, are you sure this does what I need? I'd like to perform animation on a text field before I segue back to my root view controller. So, I'm not trying to animate the transition itself when doing the segue. Just a custom animation on a text field BEFORE the view disappears. – Daniel May 25 '16 at 03:12
  • I believe you can accomplish that with this approach. You'll have control over the transition time so you know you can slow it down until things are done and you have complete control over the position of the ViewController during the animation. With a little bit of work you could freeze the position of the View Controller until all of you animations are done. Once they are done then you animate the View Controller offscreen and animate the new one on. – Richmond Watkins May 25 '16 at 03:20
  • Thanks. Do you have Swift code for this? I would've thought there would be a simpler solution - maybe some kind of "wait" method which will halt the execution of viewWillDisappear until the completion of the animation. – Daniel May 25 '16 at 03:23
  • I tried this but it doesn't seem to do anything when I unwind the segue back to the main view controller. – Daniel May 25 '16 at 09:59