I recently found some UIView animation code and noticed that it was not using the animateKeyframesWithDuration:delay:options:animations:completion:
method correctly and have since been trying to fix it but for some reason the animations are not identical.
Here's the code that I found:
view.transform = CGAffineTransformMakeTranslation(300, 0);
[UIView animateKeyframesWithDuration:duration/4 delay:delay options:0 animations:^{
// End
view.transform = CGAffineTransformMakeTranslation(-10, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
// End
view.transform = CGAffineTransformMakeTranslation(5, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
// End
view.transform = CGAffineTransformMakeTranslation(-2, 0);
} completion:^(BOOL finished) {
[UIView animateKeyframesWithDuration:duration/4 delay:0 options:0 animations:^{
// End
view.transform = CGAffineTransformMakeTranslation(0, 0);
} completion:^(BOOL finished) {
}];
}];
}];
}];
There are two problems with this:
- One should really use a key frame animation instead of nesting animations inside the completion block.
- When using
animateKeyframesWithDuration:delay:options:animations:completion:
you are supposed to call theaddKeyframeWithRelativeStartTime:relativeDuration:animations:
method inside the animation block. If you don't call this method then this method will behave like a standard UIView animation block.
See Apple's documentation regarding this method here.
So I tried to fix this by utilising the method correctly:
view.transform = CGAffineTransformMakeTranslation(300, 0);
double frameDuration = 1.0/4.0; // 4 = number of keyframes
[UIView animateKeyframesWithDuration:duration delay:delay options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(-10, 0);
}];
[UIView addKeyframeWithRelativeStartTime:1*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(5, 0);
}];
[UIView addKeyframeWithRelativeStartTime:2*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(-2, 0);
}];
[UIView addKeyframeWithRelativeStartTime:3*frameDuration relativeDuration:frameDuration animations:^{
view.transform = CGAffineTransformMakeTranslation(0, 0);
}];
} completion:nil];
I feel like both animations should be identical, however they are not. What did I do wrong in my attempt?
Edit: Example project (Use Command + T to toggle slow animations in the simulator)