Why the pause between animateWithDuration animation and completion blocks?

cocoa-touch, core-animation, uinavigationcontroller, uiview, uiviewanimationtransition

Solution

Aside: Is there any particular reason why you are abusing a navigation controller in this way? Couldn’t you just use `presentViewController:animated:completion:` setting its transition style to `UIModalTransitionStyleFlipHorizontal`?

Back to your question:

I’m pretty much sure that the stutter comes from the simple fact that `pushViewController:animated:` implicitly has to load the view of the view controller that is to be pushed and that this takes some time.

So if you cannot use the `presentViewController:animated:completion:` (or presentModalViewController:animated: if you have to support iOS 4) approach, I’d encourage you to try this:

// ensure the view is already loaded when you invoke `pushViewController:animated:`
[viewController view];

// there is no strict need to calculate those in situ, so we do it up front
CGAffineTransform originalTransform = self.view.transform;
CGAffineTransform downscalingTransform = CGAffineTransformScale(originalTransform, 0.8, 0.8);

// I found it hard to read the block-in-a-block-in-a... while editing here, so I've taken them apart:
void (^scaleDownAnimation)() = ^{
    self.view.transform = downscalingTransform;
};

void (^restoreScaleAnimation)() = ^{
    self.view.transform = originalTransform;
};

void (^pushControllerAnimation)() = ^{
    [self pushViewController:viewController animated:NO];
};

void (^pushAnimationCompletion)(BOOL) = ^(BOOL unused) {
    [UIView animateWithDuration:scaleDuration
                          delay:0
                        options:UIViewAnimationOptionCurveLinear
                     animations:restoreScaleAnimation
                     completion:nil];
};

void (^downscaleCompletion)(BOOL) = ^(BOOL unused){
    UIViewAnimationOptions linearFlipFromLeft = UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft;
    [UIView transitionWithView:self.view
                      duration:1
                       options:linearFlipFromLeft
                    animations:pushControllerAnimation
                    completion:pushAnimationCompletion];
};

[UIView animateWithDuration:scaleDuration
                      delay:0
                    options:UIViewAnimationOptionCurveEaseIn
                 animations:scaleDown
                 completion:downscaleCompletion];

Note that the beef is within the first six lines, all the rest is just for completeness.

Problem

Following Apple's recommendations, I'm chaining UIView animations by putting subsequent calls to `-animationWithDuration:animation:` in the `completion:` block of another call to `aanimateWithDuration:animation:completion:`, like so: ``` [UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ // Scale the controllers' views down. self.view.transform = CGAffineTransformScale(self.view.transform, 0.8, 0.8); } completion:^(BOOL finished) { // Transition to the new view and push on the new view controller. [UIView transitionWithView:self.view duration:1 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft animations:^{ [self pushViewController:viewController animated:NO]; } completion:^(BOOL finished) { [UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveLinear animations: ^{ // Scale back to the original size. self.view.transform = CGAffineTransformScale(self.view.transform, 1.25, 1.25); } completion:nil]; }]; }]; ``` The animations all execute the right order, but there is a tiny delay between them, especially before the `-transitionWithView:duration:options:animations:completion:` call. How do I smooth out the transitions between animation steps?

Original source

Related problems