Animate UILabel text between two numbers?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
UILabel does not support animating its text content directly with UIView animations. To animate a number counting up or down (e.g., from 0 to 100), you need a timer-based approach that updates the label text at regular intervals. The most common methods are CADisplayLink (synced to the screen refresh rate), Timer, or a custom UIViewPropertyAnimator with a progress callback.
CADisplayLink Approach (Recommended)
CADisplayLink fires on every screen refresh (60 or 120 Hz), producing the smoothest animation:
Usage:
Timer Approach (Simpler)
For simple cases where frame-perfect smoothness is not critical:
This ticks once per integer step. For large ranges (0 to 10,000), the interval becomes very small and the timer may not fire fast enough. Use CADisplayLink for large ranges.
UIView Transition Animation
To add a visual transition effect (crossfade) when the number changes:
Combine this with either approach for a polished counting effect with fade transitions.
Easing Functions
Different easing curves change the feel of the animation:
Apply inside the display link callback:
Formatting Options
SwiftUI Version
In SwiftUI, use withAnimation and the .contentTransition(.numericText()) modifier (iOS 16+):
For pre-iOS 16, use a TimelineView or Timer publisher:
Common Pitfalls
- Not invalidating CADisplayLink: If you start a new animation without invalidating the previous
CADisplayLink, multiple links fire simultaneously, causing erratic values. Always calldisplayLink?.invalidate()before creating a new one. - Memory leak from CADisplayLink target:
CADisplayLinkretains its target strongly. If the label is deallocated while the link is active, it crashes. Invalidate the display link indeinitor use a weak proxy object. - Timer precision for large ranges: A
Timerwith a 0.001s interval does not fire every millisecond — the run loop may coalesce timer events. UseCADisplayLinkfor ranges over a few hundred steps. - Forgetting to set the final value: Due to floating-point rounding, the last animated value may not exactly equal the target. Always set
label.textto the exact end value when the animation completes. - Animating on a background thread: UILabel must be updated on the main thread. Both
CADisplayLink(added to.mainrun loop) andTimer.scheduledTimer(main run loop) handle this automatically, but if you useDispatchQueue.global(), wrap the UI update inDispatchQueue.main.async.
Summary
- UILabel text cannot be animated with standard UIView animations
- Use
CADisplayLinkfor smooth, frame-synced counting animations - Use
Timerfor simple integer counting with small ranges - Apply easing functions (ease-out, ease-in-out) for natural-feeling animations
- Use
NumberFormatterfor localized number formatting (commas, currency, percentages) - In SwiftUI (iOS 16+), use
.contentTransition(.numericText())for built-in number animation
Related reading
- Animating a constraint in Swift
- Animating UILabel Font Size Change
- Any good ORM tools for Android development?
- Any good ORM tools for Android development?
- Any way to bold part of a NSString?
- API 'variant.getExternalNativeBuildTasks' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders
- app-release-unsigned.apk is not signed
- app-release.apk how to change this default generated apk name
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.