Chaining Core Animation animations
You can also use animation grouping and use the beginTime field of the animation. Try something like this:
CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"];[posAnimation setFromValue:[NSNumber numberWithFloat:0.0]];[posAnimation setToValue:[NSNumber numberWithFloat:1.0]];// Here's the important part[posAnimation setDuration:10.0];[posAnimation setBeginTime:0.0];CABasicAnimation *borderWidthAnimation = [CABasicAnimation animationWithKeyPath:@"borderWidth"];[borderWidthAnimation setFromValue:[NSNumber numberWithFloat:0.0]];[borderWidthAnimation setToValue:[NSNumber numberWithFloat:1.0]];// Here's the important part[borderWidthAnimation setDuration:10.0];[borderWidthAnimation setBeginTime:5.0];CAAnimationGroup *group = [CAAnimationGroup animation];[group setDuration:10.0];[group setAnimations:[NSArray arrayWithObjects:posAnimation, borderWidthAnimation, nil]];[layer addAnimation:group forKey:nil];
Notice that the duration of the entire animation is 10 seconds. The first one starts at second 0 and the second one starts at 5 seconds.
As Matt pointed out, you can create animation groups that consist of different animations for the same layer with different begin times. You can also set a delegate for stand-alone CAAnimation
objects or CAAnimation
Groups and as each animation finishes it will call an animationDidStop:finished:
delegate method (note that animations that are part of a group won't call their delegate's animationDidStop:finished:
method.
I figured out a cool trick that makes using the CAAnimation animationDidStop:finished:
method more powerful. I use the method setValue:forKey:
to add a block of code to a stand-alone animation or animation group, with the key @"animationCompletionBlock". I then write a general animationDidStop:finished:
method that checks the just-completed animation for a @"animationCompletionBlock" key, and if it finds it, execute the block of code there.
Take a look at this project on github for a working example of that technique:
CAAnimation demo with completion blocks
You an also Set a group of animations inside a
[CATransaction begin];//...[[CATransaction commit];
block, as you suggested. When you do that, you can using the CATransaction
class method setCompletionBlock:
to invoke a block of code when all the animations in the current transaction group complete. The completion block for one transaction can then trigger the next transaction.
I pull this off using the setCompletionBlock
method to define a closure that triggers the next animation when the first one is finished:
[CATransaction begin]layer1.property = new_property;CATransaction.setCompletionBlock { [CATransaction begin] layer2.property2 = new_property2; [CATransaction commit];}[CATransaction commit];