Skip to content

Instantly share code, notes, and snippets.

@vladimir-bebeshko
Last active December 11, 2018 09:13
Show Gist options
  • Save vladimir-bebeshko/edcbf658cb1e7a32aacd873cca2421c3 to your computer and use it in GitHub Desktop.
Save vladimir-bebeshko/edcbf658cb1e7a32aacd873cca2421c3 to your computer and use it in GitHub Desktop.
Chain Core Animations
/// Core Animation doesn't support chaining of animations by default. The `CAAnimationChain` class adds this ability.
/// The `CAAnimationSet` struct holds animation set for one target, and `CAAnimationChain` accepts an array of
/// `CAAnimationSet`s to support multiple targets.
import Foundation
class CAAnimationChain: NSObject, CAAnimationDelegate {
private var animationSets: [CAAnimationSet]
private let completion: (() -> Void)?
init(animationSets: [CAAnimationSet], completion: (() -> Void)? = nil) {
self.animationSets = animationSets
self.completion = completion
super.init()
for animationSet in animationSets {
for animation in animationSet.animations {
animation.delegate = self
}
}
}
// MARK: Chain animations
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.playNext()
}
func playNext() {
guard let animationSet = self.animationSets.first else {
if let completion = self.completion {
completion()
}
return
}
if let animation = animationSet.animations.first {
if let configuration = animationSet.configuration {
configuration()
self.animationSets[0].configuration = nil
}
animationSet.target.add(animation, forKey: "currentAnimation")
self.animationSets[0].animations.removeFirst()
} else {
if let completion = animationSet.completion {
completion()
}
self.animationSets.removeFirst()
self.playNext()
}
}
}
struct CAAnimationSet {
let target: CALayer
var animations: [CAAnimation]
var configuration: (() -> Void)?
let completion: (() -> Void)?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment