It’s really useful to fire a function when an animation is complete.
There’s no built in way to do that in CoreAnimation, it does have the concept of delegate’s, which get you half way there.
However if you have multiple animations firing, and your delegate is catching everything, you’re gonna be in for a world of hurt.
Here is a simple Swift class I wrote to extend CAAnimation to accept onStart
/onCompletion
blocks:
Updated to Swift 4 by https://gist.github.com/dagronf
//
// CAAnimation+BlockCallback.swift
//
import UIKit
//
// Modified from http://onedayitwillmake.com/blog/2016/06/caanimation-completion-callback-block/
// Updated for Swift 4 syntax
// All credit to the original author (Mario Gonzalez)
//
// USAGE:
//
// var animation = CABasicAnimation(keyPath: "strokeEnd")
// animation.duration = duration
// animation.fromValue = 0.0
// animation.toValue = 1.0
// animation.startBlock { startingAnimation, status in
// print("Starting...")
// }
// animation.completionBlock { completingAnimation, status in
// print("Completed!")
// }
public typealias CAAnimationBlockCallback = (CAAnimation, Bool) -> ();
public class CAAnimationBlockCallbackDelegate: NSObject, CAAnimationDelegate {
var onStartCallback: CAAnimationBlockCallback?
var onCompleteCallback: CAAnimationBlockCallback?
public func animationDidStart(_ anim: CAAnimation) {
if let startHandler = onStartCallback {
startHandler(anim, true)
}
}
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
if let completionHandler = onCompleteCallback {
completionHandler(anim, flag);
}
}
}
public extension CAAnimation {
// See if there is already a CAAnimationDelegate handling this animation
// If there is, add onStart to it, if not create one
func startBlock(callback: @escaping CAAnimationBlockCallback) {
if let myDelegate = self.delegate as? CAAnimationBlockCallbackDelegate {
myDelegate.onStartCallback = callback;
} else {
let callbackDelegate = CAAnimationBlockCallbackDelegate()
callbackDelegate.onStartCallback = callback
self.delegate = callbackDelegate
}
}
// See if there is already a CAAnimationDelegate handling this animation
// If there is, add onCompletion to it, if not create one
func completionBlock(callback: @escaping CAAnimationBlockCallback) {
if let myDelegate = self.delegate as? CAAnimationBlockCallbackDelegate {
myDelegate.onCompleteCallback = callback
} else {
let callbackDelegate = CAAnimationBlockCallbackDelegate()
callbackDelegate.onCompleteCallback = callback
self.delegate = callbackDelegate
}
}
}
I am unable to use it. It says ‘Method does not override any method from its super class’
Thanks for this code mate. I’ve updated it for modern swift here :-
https://gist.github.com/dagronf/35305c6a8f732ba78423cb6bf3901647
Great work!
Updated for Swift 4 here :-
https://gist.github.com/dagronf/35305c6a8f732ba78423cb6bf3901647
Thanks for the great work!