SrJaimito
SrJaimito

Reputation: 703

Curious effect when animating UIViews

I'm making squares appear at the top of the screen, run till they reach the bottom and then disappear. This is done adding a new UIView to the ViewController's view and then, after the animation is completed, removing it from the subviews array. To add some beauty to all of this, I apply a random rotation using a CGAffineTransform at the moment of their creation.

The curious thing here is that when they are moving, they are being scaled randomly! I know this must be related to the rotation, because if I don't apply it, all the squares move perfectly without scaling, but when I apply it, it happens, so...

I hope someone could test it and tell me what's happening... Why are squares scaling???

This is the code:

import UIKit

class ViewController: UIViewController {

    var timer: Timer!

    override func viewDidLoad() {
        timer = Timer.scheduledTimer(
            timeInterval: 1,
            target: self,
            selector: #selector(createView),
            userInfo: nil,
            repeats: true
        )
    }

    @objc private func createView () {
        let v = UIView(frame: CGRect(
            x: self.view.bounds.width / 2 - 50,
            y: -100,
            width: 100,
            height: 100
        ))
        v.backgroundColor = UIColor.red
        v.transform = CGAffineTransform(
            rotationAngle: CGFloat(Double(arc4random_uniform(360)) * M_PI / 180)
        )
        self.view.addSubview(v)

        UIView.animate(withDuration: 5, delay: 0, options: [.curveLinear], animations: {
            v.frame.origin.y = self.view.bounds.height
        }, completion: {
            _ in
            v.removeFromSuperview()
        })

        print(self.view.subviews.count)
    }

}

Upvotes: 1

Views: 58

Answers (1)

Duncan C
Duncan C

Reputation: 131418

The first rule of animation club is don't manipulate a view's frame when you've changed it's transform.

If a view's transform is not the identity transform then the frame is undefined, and trying to change the frame will result in undefined behavior. It sounds like you're experiencing some of that undefined behavior.

You should refactor your code to manipulate the view's center property rather than the frame, or apply your offset using the transform, but that is tricky since rotation changes the frame of reference for the offset.

I recommend adjusting the view's center property.

Upvotes: 3

Related Questions