Bartłomiej Semańczyk
Bartłomiej Semańczyk

Reputation: 61880

Animation stops working when view appears again

extension UIView {

    func startBlinking() {
        UIView.animate(withDuration: 0.8, delay: 0.0, options: [.allowUserInteraction, .curveEaseInOut, .autoreverse, .repeat], animations: { self.alpha = 0 }, completion: nil)
    }
}

How do I use it?

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    monthLabel.startBlinking()
}

When method is called first time, then it blinks... but the second time when view did appear the label disappears and... that's it.

Why doesn't it work again?

My logs:

did load
did appear
start blinking
did appear
start blinking

Upvotes: 0

Views: 425

Answers (3)

Vishnu Ps
Vishnu Ps

Reputation: 69

using CABasicAnimation solves my issue

let animation = CABasicAnimation(keyPath: "opacity")
animation.isRemovedOnCompletion = false
animation.fromValue           = 1
animation.toValue             = 0.1
animation.duration            = 0.8
animation.autoreverses        = true
animation.repeatCount         = Float.infinity
animation.beginTime           = 0.0
yourView.layer.add(animation, forKey: nil)

Upvotes: 1

Brandon
Brandon

Reputation: 23525

Try:

import UIKit

protocol Then {}

extension Then {
    func then(_ block: (Self) -> Void) -> Self {
        block(self)
        return self
    }
}

extension UIView: Then {}

class ViewController: UIViewController {

    private var animate: ((Bool) -> Void)?
    private var canAnimate: Bool = true

    override func viewDidLoad() {
        super.viewDidLoad()

        let label = UILabel().then {
            $0.text = "Hello World!"
            $0.textColor = .black
            $0.translatesAutoresizingMaskIntoConstraints = false
        }

        view.addSubview(label)
        NSLayoutConstraint.activate([
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            label.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ])

        animate = { [weak self] (forward) in
            UIViewPropertyAnimator.runningPropertyAnimator(withDuration: 1.0, delay: 0.0, options: [.curveLinear, .autoreverse, .repeat], animations: {

                label.alpha = forward ? 0.0 : 1.0

            }, completion: { [weak self] _ in
                if self?.canAnimate ?? true {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: {
                        self?.animate?(!forward)
                    })
                }
            }).startAnimation()
        }

        animate?(true)

     DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            let controller = UIViewController()
            self.navigationController?.pushViewController(controller, animated: true)
        }
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        canAnimate = false
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        canAnimate = true
        animate?(true)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Upvotes: 2

Shehata Gamal
Shehata Gamal

Reputation: 100551

You need to restart the alpha

func startBlinking() {
    self.layer.removeAllAnimations() 
    self.alpha = 1.0
    UIView.animate(withDuration: 0.8, delay: 0.0, options: [.allowUserInteraction, .curveEaseInOut], animations: { self.alpha = 0.0 }, completion: nil)
}

Upvotes: 1

Related Questions