Search code examples
iosswiftcore-animationuiviewanimation

Animating several consecutive UILabels at the same speed at the same time to the same point


I have 5 consecutive UILabel like this:

enter image description here

They were created with the same frame than the label 1 and then were moved using a CGAffineTransform property. So a CGAffineTransformIdentity will bring them all back on top of label 1.

I would like, when I press a button, to move them all back to the label 1, at the same speed and once they reach their destination, remove them from their superview.

So far I've done like the following but it doesn't work:

var reversedLabels = getLabels().reverse()
let duration: NSTimeInterval = 5
UIView.animateWithDuration(duration, animations: {
    for (index, label) in enumerate(reversedLabels) {
        let relativeDuration: NSTimeInterval = duration * Double(index) / Double(reversedLabels.count)

        UIView.animateWithDuration(relativeDuration, animations: {
            label.transform = CGAffineTransformIdentity
            }, completion: { finished in
                label.hidden = true
        })
    }
    }, completion: { finished in
        for (index, label) in enumerate(reversedLabels) {
            label.removeFromSuperview()
        }
})

The completion of the main animation gets called before the completions of the nested animations. Then I guess it's not the way to do it.

How would you do it? (and why the "final" completion isn't called at the very end?)


Solution

  • Since you are not animating any animatable property of any view inside first animation block, the completion block will get executed immediately after animation start. What I cant understand is why do you need that block at all. In completion of inner animations you are hiding your labels, which is the same UI behaviour as removing them from superview, so maybe this block of code (without outer animation) might bring to you the desired result

    for (index, label) in enumerate(reversedLabels) {
    
        let relativeDuration: NSTimeInterval = duration * Double(index) / Double(reversedLabels.count)
    
        UIView.animateWithDuration(relativeDuration, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
    
                label.transform = CGAffineTransformIdentity
    
                }, completion: {finished in
                label.removeFromSuperview()=
            })
    }
    

    EDITED : relativeDuration should be calculating by adding +1 to index otherwise first animation will have 0 duration. Also to achieve same speed for all animations you should use UIViewAnimationOptions.CurveLinear