Umar Yaqub Umar Yaqub - 6 months ago 57
Swift Question

Infinitely rotate two variables using CAAnimation

I am calling users "Weight" from firebase database in a label (which is stored under 'profile/uid') which has two categories "kg" and "lbs". I would like the label to be able to show user's weight in kg and then fade out to lbs and then back to kg again so on and so fourth. So far i have written the following code which is constantly fading in and out the weight in lbs and i'm unsure how to get it to display the weight in kg once lbs fades out:

func weight() {

let userRf = self.firDatabaseRef.child("profile").child("\(User!.uid)").observe(FIRDataEventType.value, with: { (snapshot) in
if snapshot.exists() {
if let weight = snapshot.childSnapshot(forPath: "weight").value as? [String: AnyObject] {
if let kg = weight["kg"] as? Float, let lbs = weight["lbs"] as? Int {

let animation: CATransition = CATransition()
animation.duration = 2.0
animation.type = kCATransitionFade
animation.repeatDuration = .infinity
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
self.displayWeight.layer.add(animation, forKey: "changeTextTransition")

self.displayWeight.text = "\(lbs) lbs"

}
}
}
}

}

Answer Source

One way is to use a repeating UIVIew animation along with a Timer:

// set up some helpful constants
let kgsText = "\(kgs) kgs"
let lbsText = "\(lbs) lbs"
let fadeDuration = 2.0

// keep track of which unit is being displayed
var isDisplayingKgs = true

// animate the fade in and out, repeating
UIView.animate(withDuration: fadeDuration, delay: 0, options: [.autoreverse, .repeat], animations: {
    label.alpha = 0
}, completion: nil)

// start the timer to switch the text after a short delay
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + fadeDuration) {
    self.displayWeight.text = lbsText
    isDisplayingKgs = false
    Timer.scheduledTimer(withTimeInterval: fadeDuration * 2, repeats: true, block: { timer in
        self.displayWeight.text = isDisplayingKgs ? lbsText : kgsText
        isDisplayingKgs = !isDisplayingKgs
    })
}

This is assuming that your label starts out visible (alpha = 1). The dispatch delay is to ensure that the first transition occurs when the label is faded out the first time, but before the timer kicks in.

Here is what the animation looks like in action:

gif of the label animation