CAKeyframeAnimation delay before repeating

samvermette picture samvermette · Mar 3, 2013 · Viewed 10.4k times · Source

I have a CAKeyframeAnimation animation that I would like to repeat forever using repeatCount = HUGE_VALF. The animation's duration is 2 seconds, but I would like to have a 3 seconds pause before each cycle.

The only 2 ways I can think of doing that are:

  1. Make the whole animation last 5 seconds and add extra keyTimes and values so that I get the pause I'm looking for during the last 3s of the 5s animation. This feels kinda hacky.

  2. Have the animation only repeat once and then add use something like performSelector:afterDelay:2 to run the animation again, and so on and so on. This feels dirty as well. Also would mean that I need to call addAnimation: every 5 seconds, which I'm not sure is optimal in terms of performance.

Is there another option I might be missing? Is one of those 2 methods better than the other?

Answer

samvermette picture samvermette · Mar 4, 2013

By dumping the animations of Apple's MKUserLocationView, I was able to see how they were doing it. Turns out that this is what CAAnimationGroup is for. By encapsulating a 2 seconds animation into a 5 seconds animation group, you'll end up with a 2 seconds animation followed by a 3 seconds delay:

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 5;
animationGroup.repeatCount = INFINITY;

CAMediaTimingFunction *easeOut = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

CABasicAnimation *pulseAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.xy"];
pulseAnimation.fromValue = @0.0;
pulseAnimation.toValue = @1.0;
pulseAnimation.duration = 2;
pulseAnimation.timingFunction = easeOut;

animationGroup.animations = @[pulseAnimation];

[ringImageView.layer addAnimation:animationGroup forKey:@"pulse"];