Lottie is the standard way to ship After Effects animations in iOS apps. It renders animations natively â no WebView, no GIF, no frame-dropping. This guide covers everything from setup to advanced playback control using the official lottie-ios library.
Why Lottie for iOS?
- Native rendering via Core Animation â no WebView overhead
- Vector-based â crisp on all screen densities, including ProMotion 120Hz displays
- Tiny files â a 3-second loading animation is typically under 15KB
- Full control â play, pause, loop, seek to specific frames programmatically
- Both UIKit and SwiftUI supported
Step 1: Before You Add the File â Preview It First
Before dropping any Lottie file into Xcode, preview it in IconKing:
- See exactly how the animation looks (colors, timing, layers)
- Edit colors to match your iOS app's design system
- Convert
.jsonâ.lottieformat (75% smaller file size) - Catch broken layers or missing fonts before they cause issues at runtime
No account needed. Drop the file, inspect, adjust, download.
Step 2: Install lottie-ios
Swift Package Manager (recommended)
- In Xcode, go to File â Add Package Dependencies
- Enter:
https://github.com/airbnb/lottie-spm.git - Select Up to Next Major Version from
4.0.0 - Click Add Package
CocoaPods
pod 'lottie-ios'
Run:
pod install
Step 3: Add Your Animation File
- Drag your
.jsonor.lottiefile into your Xcode project - Make sure "Add to targets" is checked for your app target
- Verify the file appears in Build Phases â Copy Bundle Resources
Step 4: Basic Usage (UIKit)
import UIKit
import Lottie
class LoadingViewController: UIViewController {
private var animationView: LottieAnimationView!
override func viewDidLoad() {
super.viewDidLoad()
animationView = LottieAnimationView(name: "loading")
animationView.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
animationView.center = view.center
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.play()
view.addSubview(animationView)
}
}
name: matches the filename without extension (e.g., loading.json â "loading").
Step 5: Basic Usage (SwiftUI)
import SwiftUI
import Lottie
struct LoadingView: View {
var body: some View {
LottieView(animation: .named("loading"))
.playing(loopMode: .loop)
.frame(width: 200, height: 200)
}
}
For SwiftUI, use LottieView (added in lottie-ios 4.0).
Loop Modes
// Loop forever
animationView.loopMode = .loop
// Play once and stop
animationView.loopMode = .playOnce
// Ping-pong (forward then backward)
animationView.loopMode = .autoreverse
// Repeat 3 times then stop
animationView.loopMode = .repeat(3)
Playback Control
// Play from current position
animationView.play()
// Play with completion handler
animationView.play { completed in
if completed {
print("Animation finished")
}
}
// Pause
animationView.pause()
// Stop and reset to beginning
animationView.stop()
// Play specific frame range
animationView.play(fromFrame: 0, toFrame: 60, loopMode: .playOnce)
Speed Control
// Half speed
animationView.animationSpeed = 0.5
// Double speed
animationView.animationSpeed = 2.0
// Reverse
animationView.animationSpeed = -1.0
Seek to a Specific Frame
// Jump to frame 30
animationView.currentFrame = 30
// Jump to normalized progress (0.0 to 1.0)
animationView.currentProgress = 0.5
Dynamic Color Replacement
Override colors at runtime without editing the source file:
let colorProvider = ColorValueProvider(UIColor.systemBlue.lottieColorValue)
animationView.setValueProvider(colorProvider, keypath: AnimationKeypath(keypath: "**.Fill 1.Color"))
The keypath uses the layer/property structure from After Effects. To find the right keypath, open the .json file and inspect the layers â or use IconKing to browse the layer structure before writing code.
Using dotLottie (.lottie) Format
dotLottie files are ~75% smaller than .json. For lottie-ios 4.4+:
// Load from bundle
let animation = LottieAnimation.named("loading") // works for both .json and .lottie
// The library detects the format automatically
animationView = LottieAnimationView(animation: animation)
To convert your .json to .lottie, use IconKing â drop the file, click convert, download. The converted file will be significantly smaller, which matters for app bundle size.
Loading from a URL
LottieAnimation.loadedFrom(url: URL(string: "https://example.com/animation.json")!) { animation in
guard let animation = animation else { return }
DispatchQueue.main.async {
self.animationView.animation = animation
self.animationView.play()
}
}
Performance Tips
1. Stop animations when not visible
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
animationView.stop()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
animationView.play()
}
2. Use .lottie format over .json
Smaller bundle size, faster loading. Convert at IconKing.
3. Use renderingEngine: .coreAnimation for complex animations
let animationView = LottieAnimationView(
name: "complex-animation",
configuration: LottieConfiguration(renderingEngine: .coreAnimation)
)
Core Animation rendering uses the GPU and is significantly faster for animations with many layers.
Complete Example: Splash Screen
import UIKit
import Lottie
class SplashViewController: UIViewController {
private var animationView: LottieAnimationView!
var onComplete: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupAnimation()
}
private func setupAnimation() {
animationView = LottieAnimationView(name: "splash")
animationView.translatesAutoresizingMaskIntoConstraints = false
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .playOnce
view.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
animationView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
animationView.widthAnchor.constraint(equalToConstant: 250),
animationView.heightAnchor.constraint(equalToConstant: 250)
])
animationView.play { [weak self] _ in
self?.onComplete?()
}
}
}
Common Issues
"Animation not found" crash
The file isn't in the bundle. Check:
- The file is added to Build Phases â Copy Bundle Resources
- The filename matches exactly (case-sensitive on device)
Animation looks different on device vs. preview
Preview in IconKing first. If it looks correct there, the issue is likely contentMode or a rendering engine mismatch. Try switching between .automatic and .coreAnimation rendering.
Colors look wrong
lottie-ios 4.x changed how some color modes render vs. the older library. Use setValueProvider to override colors at runtime rather than hardcoding them in the JSON.
Finding Lottie Files for iOS
- LottieFiles â large free library
-
IconKing â preview any file, edit colors to match your app's palette, convert between
.jsonand.lottieformats before adding to Xcode
Always preview before adding to your project. A file that looks great on desktop might have clipped bounds or unexpected behavior at iOS screen sizes â IconKing lets you catch this in the browser before it becomes an Xcode problem.
Summary
- Install
lottie-iosvia SPM or CocoaPods - Add your animation file to the Xcode bundle
- Use
LottieAnimationView(UIKit) orLottieView(SwiftUI) - Set
loopMode, call.play() - Override colors with
setValueProviderif needed - Convert to
.lottieat IconKing for smaller app size - Use Core Animation rendering engine for complex animations
Top comments (0)