Animation End Callback for CALayer?

Viewed 58162

I'm wondering where the callbacks are (or if there are anything) for animations in a CALayer. Specifically, for implied animations like altering the frame, position, etc. In a UIView, you could do something like this:

[UIView beginAnimations:@"SlideOut" context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animateOut:finished:context:)];
CGRect frame = self.frame;
frame.origin.y = 480;
self.frame = frame;
[UIView commitAnimations];

Specifically, the setAnimationDidStopSelector is what I want for an animation in a CALayer. Is there anything like that?

TIA.

11 Answers

I answered my own question. You have to add an animation using CABasicAnimation like so:

CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"frame"];
anim.fromValue = [NSValue valueWithCGRect:layer.frame];
anim.toValue = [NSValue valueWithCGRect:frame];
anim.delegate = self;
[layer addAnimation:anim forKey:@"frame"];

And implement the delegate method animationDidStop:finished: and you should be good to go. Thank goodness this functionality exists! :D

Swift 5.0

func blinkShadow(completion: @escaping (() -> Void)) {
    CATransaction.begin()
    let animation = CABasicAnimation(keyPath: "shadowRadius")
    animation.fromValue = layer.shadowRadius
    animation.toValue = 0.0
    animation.duration = 0.1
    animation.autoreverses = true
    CATransaction.setCompletionBlock(completion)
    layer.add(animation, forKey: nil)
    CATransaction.commit()
}

For 2020 ...

ValueAnimator, update ur custom properties.

https://github.com/Only-IceSoul/ios-jjvalueanimator

 class OnAnimationListener : AnimatorListener {

        weak var s : ViewController?

        init(_ ins: ViewController) {
            s = ins
        }
        func onAnimationStart(_ animation: Animator) {}
        func onAnimationEnd(_ animation: Animator) {

           print("end")
           s?.label.text = "end"

        }
        func onAnimationCancel(_ animation: Animator) {}
        func onAnimationRepeat(_ animation: Animator) {}

    }

I wrote an extension on CAAnimation which gives you a began & a finished closure, as I was getting fed up of implementing the delegate, especially for multiple animations where you'd have to do horrible stuff like using the animation's key to see which animation was calling the delegate - makes this sort of thing really easy.

It's on GitHub - Animation Actions

Hopefully useful to someone!

Related