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?
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 toUIModalTransitionStyleFlipHorizontal
?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:Note that the beef is within the first six lines, all the rest is just for completeness.
I've chained animations as you describe with no delay.
You are using transitionWithView:duration:options:animations:completion: with the animation block being a call to pushViewController:animated:. That doesn't make any sense to me.
transitionWithView:duration:options:animations:completion transitions from one subview to the next.
pushViewController:animated is a navigation controller method that pushes a view controller on the navigation controller stack. Using those 2 together makes no sense to me.
If you want your scale animation to end with a push, then just call the push animation directly from your completion block.
In my experience, the "use the completion block to chain animations" is simply flawed (makes small pauses between sub-animations). I made sure there's no loadView/viewDidLoad/viewWillAppear/viewWillLayoutSubviews abuse going on.
The exact same code stutters with "completion-block_chainig" but works just fine if I rework it to use keyframes.
So, instead of (for example)...
... I instead prefer...