- Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
The animate method of UIView only performs Frame, alpha, color, and transform operations on a UIView. So you can’t do all of these with UIView animate. Here’s what you need — CADisplaylink, a timer object that allows your app to synchronize its drawing based on the screen refresh rate.
1. Establish CADisplaylink
Start by creating a Label.
let countingLabel: UILabel = {
let label = UILabel()
label.text = "1234"
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 18)
return label
}()
Copy the code
Add it to the subview and give it a frame.
view.addSubview(countingLabel)
countingLabel.frame = view.frame
Copy the code
Then create a CADisplayLink and add it to the main thread runloop.
let displayLink = CADisplayLink(target: self, selector: #selector(handleUpdate))
displayLink.add(to: .main, forMode: .default)
Copy the code
2. Start and end values
Create start and end values
Var startValue = 0.0 let endValue = 1200.0Copy the code
So if I go ahead and do a little bit of code inside the displayLink response method and I run it, I can see that the number inside the Label is bouncing.
@objc func handleUpdate() {
self.countingLabel.text = "\(startValue)"
startValue += 1
if startValue > endValue {
startValue = endValue
}
}
Copy the code
3. Animation duration
Gets the current time and sets the desired duration
Let animationDuration = 1.5 let animationStartDate = Date()Copy the code
Then modify the handleUpdate method to change the value of the UILabel based on the past time and the set animation duration.
@objc func handleUpdate() {
let now = Date()
let elapsedTime = now.timeIntervalSince(animationStartDate)
if elapsedTime > animationDuration {
self.countingLabel.text = "\(endValue)"
} else {
let percentage = elapsedTime / animationDuration
let value = startValue + percentage * (endValue - startValue)
self.countingLabel.text = "\(value)"
}
}
Copy the code
There are two more problems here, one is the removal of displayLink, and one is the decimal point after the value. To remove displayLink the problem is to move displayLink outside as a VC property and then remove it after the animation. And to solve the decimal problem, you just convert it to an Int. Final code:
import UIKit class ViewController: UIViewController { let countingLabel: UILabel = { let label = UILabel() label.text = "1234" label.textAlignment = .center label.font = UIFont.boldSystemFont(ofSize: 18) return label }() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.addSubview(countingLabel) countingLabel.frame = view.frame displayLink = CADisplayLink(target: self, selector: #selector(handleUpdate)) displayLink?.add(to: .main, forMode: .default)} var startValue = 0.0 let endValue = 1200.0 var displayLink: CADisplayLink? Let animationDuration = 1.5 let animationStartDate = Date() @objc func handleUpdate() {let now = Date() let elapsedTime = now.timeIntervalSince(animationStartDate) if elapsedTime > animationDuration { self.countingLabel.text = "\(Int(endValue))" displayLink?.invalidate() displayLink = nil } else { let percentage = elapsedTime / animationDuration let value = startValue + percentage * (endValue - startValue) self.countingLabel.text = "\(Int(value))" } } }Copy the code