Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CAGradientLayer color change animation not executing

I'm trying to get a very basic CAGradientLayer animation to work. I have a basic 2 color CAGradientLayer set up and added to my UIViewController.

// Set up the gradient layer.
var gradientLayer: CAGradientLayer! {
    let layer = CAGradientLayer()
    layer.frame = self.view.bounds
    layer.colors = [UIColor.redColor().CGColor, UIColor.yellowColor().CGColor]
    layer.locations = [0.0, 1.0]
    return layer
}

I am trying to animate it with the following code:

@IBAction func changeBackground(sender: AnyObject) {
    let oldColors = self.gradientLayer.colors
    let newColors = [UIColor.purpleColor().CGColor, UIColor.blueColor().CGColor]
    self.gradientLayer.colors = newColors
    let animation: CABasicAnimation = CABasicAnimation(keyPath: "colors")

    animation.fromValue = oldColors
    animation.toValue = newColors
    animation.duration = 0.3
    animation.removedOnCompletion = true
    animation.fillMode = kCAFillModeForwards
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.delegate = self

    self.gradientLayer.addAnimation(animation, forKey: "animateGradientColorChange")
}

However, this code does not yield any change in the CAGradientLayer. What am I doing wrong here ?

like image 776
Sam Fischer Avatar asked Dec 29 '25 09:12

Sam Fischer


1 Answers

You are returning a new layer object every time from your gradientLayer property. You need to change it a bit, so that it is lazily initiated :

lazy var gradientLayer: CAGradientLayer! = {
    let layer = CAGradientLayer()
    layer.frame = self.view.bounds
    layer.colors = [UIColor.redColor().CGColor, UIColor.yellowColor().CGColor]
    layer.locations = [0.0, 1.0]
    return layer
}()

For completeness sake, what you had originally was a computed property, which meant that the code was executed each time you accessed it. With lazy properties, the code is executed only once, when the property is first accessed, and then the same object is returned.

The difference can be observed with this playground :

//: Playground - noun: a place where people can play

import UIKit

struct Dummy {

    var gradientLayer: CAGradientLayer! {
        let layer = CAGradientLayer()
        layer.colors = [UIColor.redColor().CGColor, UIColor.yellowColor().CGColor]
        layer.locations = [0.0, 1.0]
        return layer
    }

    lazy var lazyGradientLayer: CAGradientLayer! = {
        let layer = CAGradientLayer()
        layer.colors = [UIColor.redColor().CGColor, UIColor.yellowColor().CGColor]
        layer.locations = [0.0, 1.0]
        return layer
    }()
}

var dummy = Dummy()

let l1 = dummy.gradientLayer
let l2 = dummy.gradientLayer

let lazy1 = dummy.lazyGradientLayer
let lazy2 = dummy.lazyGradientLayer
like image 134
Losiowaty Avatar answered Dec 30 '25 23:12

Losiowaty



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!