CAAnimation has an informal a formal—as of iOS 10—delegate protocol for informing an object when an animation starts or stops, which is useful in many cases. However, with the advent of blocks and closures, using delegates for this type of thing can be cumbersome, especially if you are managing several animations. UIKit introduced convenient, block-based animation methods, yet Core Animation never did the same. Let’s fix that.
CAAnimation has two functions for responding to animation events: starting and stopping. CAAnimation calls those functions on its delegate, if it exists, during its running lifecycle.
Because animation objects are added to layers, we can create a CALayer extension that declares a couple of convenience functions for adding animations and includes lifecycle closures:
We can create a private class that acts as the animation’s delegate and holds both LayerAnimationBeginClosure and LayerAnimationCompletionClosure:
Then we can implement the CALayer extension functions we declared above: 1
Now we have convenient, closure-based access to CAAnimation’s lifecycle functions when we add CALayer animations:
Here’s a Gist of the code we went over today, along with a few other conveniences:
CAAnimation actually holds a strong reference to its delegate per the documentation, so the animation delegate class we initialize will stick around long enough to do its job. In fact, that is the reason why CAAnimation breaks the conventional memory management rules for delegate objects: if it was weak, the animation wouldn’t be able to guarantee that its delegate still existed after a potentially lengthy duration. ↩