Search code examples
iosswiftuiimageviewuiviewanimationcompletion

Animation not stoping using UIView.animate


My code is using a simple loop animation that is not stopping after the 5 second duration. All I want to do is have a second button that stops the animation. As you can see in my code, circle.stopAnimating() has no effect.

class VET: UIViewController {
    @IBOutlet weak var circle: UIImageView!
    var duration = 5

    @IBAction func start(_ sender: Any) {
        UIView.animate(withDuration: TimeInterval(duration), delay: 0.5, options: [.repeat, .autoreverse, .curveEaseIn, .curveEaseOut], animations: { () -> Void in
            let scale = CGAffineTransform(scaleX: 0.25, y: 0.25)
            self.circle.transform = scale
            print("animation")
        }, completion: { _ in
            //if finished { or (finished: Bool)
            // if isAnimating {
            if self.circle.isAnimating {
                self.circle.stopAnimating()
                print("is animating -- stop animating")
            } else {
                self.circle.startAnimating()
                print("start animating")
            }
        })
    }

    @IBAction func stop() {
        circle.stopAnimating()
    }

Solution

  • startAnimating and stopAnimating for change images of imageview in some interval like GIF. Here you used animation block with repeat and the completion block will only get called when the animation is interrupted. For example it gets called when the app goes in the background and comes back to the foreground again.

    To stop animation after some interval you have to call forcefully removeAllAnimations after that interval. Please refer following code:

    @IBOutlet weak var circle: UIImageView!
    var duration = 10
    
    func start() {
        UIView.animate(withDuration: TimeInterval(duration), delay: 0.5, options: [.repeat, .autoreverse, .curveEaseIn, .curveEaseOut], animations: { () -> Void in
            let scale = CGAffineTransform(scaleX: 0.25, y: 0.25)
            self.circle.transform = scale
            DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(self.duration * 1000)) {
                // Code
                self.circle.layer.removeAllAnimations()
            }
    
            print("animation")
        }, completion: { _ in
    
            let scale = CGAffineTransform(scaleX: 1.0, y: 1.0)
            self.circle.transform = scale
        })
    }