Fantattitude
Fantattitude

Reputation: 1842

CABasicAnimation byValue strange behavior

I was reading the 12th number of Objc.io and encountered a problem when trying the first pieces of code. In the first part "A Basic Animation" the last piece of code uses byValue to interpolate a property using initial property value and adding byValue.

So I tried the code in my project and discovered it wasn't working and had a really strange behavior.

Here's a very short gif illustrating the problem :

Gif video illustrating the bug

And here's the only code I'm using :

class ViewController: UIViewController {

    var rocket1: UIView!
    var rocket2: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        rocket1 = UIView(frame: CGRect(x: 20, y: 100, width: 50, height: 20))
        rocket1.backgroundColor = UIColor.redColor()
        rocket2 = UIView(frame: CGRect(x: 20, y: 150, width: 50, height: 20))
        rocket2.backgroundColor = UIColor.blueColor()

        self.view.addSubview(rocket1)
        self.view.addSubview(rocket2)

    }

    @IBAction func button() {
        let animation = CABasicAnimation(keyPath: "position.x")
        animation.byValue = 300
        animation.duration = 1

        rocket1.layer.addAnimation(animation, forKey: "basic")
        rocket1.layer.position.x += 300

        animation.beginTime = CACurrentMediaTime() + 0.5

        rocket2.layer.addAnimation(animation, forKey: "basic")
        rocket2.layer.position.x += 300

    }
}

If you want to try the project here's the full project (use iPhone 6 simulator or shapes will be hidden because 5S is too "short") : https://dl.dropboxusercontent.com/u/378166/VCoreAnimation.zip

Upvotes: 0

Views: 597

Answers (1)

Erakk
Erakk

Reputation: 922

you should create a completion block for this animation like this:

@IBAction func button() {
    let animation = CABasicAnimation(keyPath: "position.x")
    animation.byValue = 300
    animation.duration = 1

    CATransaction.begin()
    CATransaction.setCompletionBlock({
        rocket1.layer.position.x += 300
    })
    rocket1.layer.addAnimation(animation, forKey: "basic")
    CATransaction.commit()

    animation.beginTime = CACurrentMediaTime() + 0.5

    CATransaction.begin()
    CATransaction.setCompletionBlock({
        rocket2.layer.position.x += 300
    })
    rocket2.layer.addAnimation(animation, forKey: "basic")
    CATransaction.commit()
}

In this case we need 2 CATransaction blocks since we have 2 animations running with a time diference from each other.

Upvotes: 1

Related Questions