So I've got a background view with a gradient sublayer, animating continuously to change the colors slowly. I'm doing it with a CATransaction, because I need to animate other properties as well:
CATransaction.begin()
gradientLayer.add(colorAnimation, forKey: "colors")
// other animations
CATransaction.setCompletionBlock({
// start animation again, loop forever
}
CATransaction.commit()
Now I want to replicate this gradient animation, let's say, for the title of a button for instance.
Note 1: I can't just "make a hole" in the button, if such a thing is possible, because I might have other opaque views between the button and the background.
Note 2: The gradient position on the button is not important. I don't want the text gradient to replicate the exact colors underneath, but rather to mimic the "mood" of the background.
So when the button is created, I add its gradient sublayer to a list of registered layers, that the background manager will update as well:
func register(layer: CAGradientLayer) {
let pointer = Unmanaged.passUnretained(layer).toOpaque()
registeredLayers.addPointer(pointer)
}
So while it's easy to animate the text gradient at the next iteration of the animation, I would prefer that the button starts animating as soon as it's added, since the animation usually takes a few seconds. How can I copy the background animation, i.e. set the text gradient to the current state of the background animation, and animate it with the right duration left and timing function?

The solution was indeed to use the
beginTimeproperty, as suggested by @Shivam Gaur's comment. I implemented it as follows: