0

I'm attempting to create a CALayer subclass that performs an animation every x seconds. In the example below I'm attempting to change the background from one random color to another but when running this in the playground nothing seems to happen

import UIKit
import XCPlayground
import QuartzCore

let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 200, height: 200))
XCPShowView("view", view)

class CustomLayer: CALayer {

    var colors = [
        UIColor.blueColor().CGColor,
        UIColor.greenColor().CGColor,
        UIColor.yellowColor().CGColor
    ]

    override init!() {
        super.init()

        self.backgroundColor = randomColor()

        let animation = CABasicAnimation(keyPath: "backgroundColor")

        animation.fromValue = backgroundColor
        animation.toValue = randomColor()
        animation.duration = 3.0
        animation.repeatCount = Float.infinity

        addAnimation(animation, forKey: "backgroundColor")

    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    private func randomColor() -> CGColor {
        let index = Int(arc4random_uniform(UInt32(colors.count)))
        return colors[index]
    }
}

let layer = CustomLayer()
layer.frame = view.frame
view.layer.addSublayer(layer)
Kyle Decot
  • 20,715
  • 39
  • 142
  • 263
  • From what I can see, you have the same "from" and "to" values for all repetitions of the animation. – David Rönnqvist Apr 01 '15 at 15:16
  • Is the problem that you don't get any animation at all? – David Rönnqvist Apr 01 '15 at 15:18
  • Yes. No animation happens. I get a random color and nothing after. @DavidRönnqvist I see what your saying but how would I implement the animation in such a way that it "asks" for a new color for each repeat of the animation? – Kyle Decot Apr 01 '15 at 15:19
  • If it animates between new values it's no longer the _same_ animation. Create a new animation and add that to the layer. – David Rönnqvist Apr 01 '15 at 15:21
  • Related to not getting any animation in a playground: I would close your question as a duplicate of [CABasicAnimation in Swift Playground](http://stackoverflow.com/questions/25235362/cabasicanimation-in-swift-playground). But that question doesn't have an accepted answer, so I can't close it as a duplicate. – David Rönnqvist Apr 01 '15 at 15:25

1 Answers1

1

The parameters of a repeating animation are only setup once, so you can't change the color on each repeat. Instead of a repeating animation, you should implement the delegate method, animationDidStop:finished:, and call the animation again from there with a new random color. I haven't tried this in a playground, but it works ok in an app. Notice that you have to implement init!(layer layer: AnyObject!) in addition to the other init methods you had.

import UIKit

class CustomLayer: CALayer {

    var newColor: CGColorRef!

    var colors = [
        UIColor.blueColor().CGColor,
        UIColor.greenColor().CGColor,
        UIColor.yellowColor().CGColor
    ]

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init!(layer: AnyObject!) {
        super.init(layer: layer)
    }

    override init!() {
        super.init()
        backgroundColor = randomColor()
        newColor = randomColor()
        self.animateLayerColors()
    }


    func animateLayerColors() {
        let animation = CABasicAnimation(keyPath: "backgroundColor")
        animation.fromValue = backgroundColor
        animation.toValue = newColor
        animation.duration = 3.0
        animation.delegate = self

        addAnimation(animation, forKey: "backgroundColor")
    }

    override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
        backgroundColor = newColor
        newColor = randomColor()
        self.animateLayerColors()
    }


    private func randomColor() -> CGColor {
        let index = Int(arc4random_uniform(UInt32(colors.count)))
        return colors[index]
    }
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218