Swift and SwiftUI tutorials for Swift Developers

Best SwiftUI Animation Libraries

If there is one thing that differentiates a “good app” from a “memorable app,” it is movement. As an iOS Developer, you know that User Experience (UX) isn’t just about the application working, but about how it feels when it works. In the Apple ecosystem, fluidity is law.

With the arrival of SwiftUI, Swift programming took a quantum leap towards simplicity. Native animations (withAnimation, .transition, .matchedGeometryEffect) are powerful, but sometimes, we need to go a step further. We need complex vector graphics, particle effects, or transitions that would make Core Animation sweat if we had to write them from scratch.

In this tutorial, we will explore the best libraries for animations in SwiftUI that you can integrate into your Xcode project today. We won’t just list tools; we will teach you how to implement them in a cross-platform architecture covering iOS, macOS, and watchOS.

Why use external libraries in SwiftUI?

Before getting our hands dirty with code, it is fair to ask: Is SwiftUI not good enough?

The short answer is: Yes, but it depends. SwiftUI is excellent for state transitions and view movement (layout changes). However, when we talk about:

  1. Complex micro-interactions: Like a “Like” icon exploding into fireworks.
  2. Animated illustrations: Walking characters or onboarding graphics.
  3. Performance in heavy animations: Rendering that requires optimization at the Metal level without writing shaders manually.

This is where third-party libraries come in. They save hundreds of hours of design and development. Let’s analyze the three crown jewels that every Swift expert should have in their toolbox.

1. Lottie (Airbnb): The Industry Standard

If you have worked as an iOS Developer for more than a year, you have surely heard of Lottie. Created by Airbnb, this library allows you to render Adobe After Effects animations exported as JSON (using the Bodymovin plugin) natively on mobile.

What makes Lottie special for SwiftUI nowadays is that we no longer need to manually wrap it in a clunky UIViewRepresentable; the library has matured to offer native and fluid support.

Installation in Xcode

  1. Open your project in Xcode.
  2. Go to File > Add Packages Dependencies.
  3. Search for the URL: https://github.com/airbnb/lottie-ios.git.
  4. Select the latest version (make sure it is 4.0 or higher for better SwiftUI support).

Cross-Platform Implementation

The following code creates a reusable view that works on iOS, macOS, and watchOS.

import SwiftUI
import Lottie

// A generic view to load Lottie animations
struct LottieView: View {
    var filename: String
    var loopMode: LottieLoopMode = .playOnce
    var contentMode: UIView.ContentMode = .scaleAspectFit
    
    var body: some View {
        LottieAnimationViewWrapper(
            filename: filename,
            loopMode: loopMode,
            contentMode: contentMode
        )
    }
}

// Wrapper to use Lottie view in SwiftUI
struct LottieAnimationViewWrapper: UIViewRepresentable {
    let filename: String
    let loopMode: LottieLoopMode
    let contentMode: UIView.ContentMode
    
    func makeUIView(context: Context) -> some UIView {
        let view = UIView(frame: .zero)
        let animationView = LottieAnimationView()
        
        // Animation configuration
        animationView.animation = LottieAnimation.named(filename)
        animationView.contentMode = contentMode
        animationView.loopMode = loopMode
        animationView.play()
        
        // Constraints to fill the space
        animationView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(animationView)
        
        NSLayoutConstraint.activate([
            animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
            animationView.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
        
        return view
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {
        // Here you could update states if necessary
    }
}

Note for macOS: Instead of UIViewRepresentable and UIView, you should use NSViewRepresentable and NSView. You can use conditional compilation #if os(macOS) to handle this in a single file.

When to use Lottie?

  • Onboardings.
  • “Success” or “Error” screens.
  • Custom branded loaders.

2. Rive: The Interactive Evolution

If Lottie is a video, Rive is a video game. Rive is one of the most promising libraries for animations in SwiftUI because it allows interactivity. You don’t just play an animation; you can change its states (State Machines) based on user inputs (clicks, scroll, mouse movements).

Rive is extremely fast because it has its own rendering engine and the files are tiny compared to Lottie or GIFs.

Integration into your Swift workflow

Rive shines when you need the animation to react to your Swift programming logic.

  1. Add the package: https://github.com/rive-app/rive-ios.
  2. Import the .riv files into your project in Xcode.

Tutorial: An Interactive Button

Imagine an “Upload” button that has states: idle, loading, and completed. In Rive, this is handled with a State Machine.

import SwiftUI
import RiveRuntime

struct InteractiveUploadButton: View {
    // The Rive ViewModel controls the animation logic
    @StateObject var riveParams = RiveViewModel(fileName: "upload_icon", stateMachineName: "UploadState")
    @State var isUploading = false
    
    var body: some View {
        VStack {
            // The Rive view
            riveParams.view()
                .frame(width: 100, height: 100)
                .onTapGesture {
                    startUpload()
                }
            
            Text(isUploading ? "Uploading..." : "Tap to upload")
                .font(.caption)
                .foregroundColor(.gray)
        }
    }
    
    func startUpload() {
        isUploading = true
        // Trigger the 'start' input defined in the Rive editor
        riveParams.setInput("start", value: true)
        
        // Simulate a network operation
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            isUploading = false
            // Trigger the 'done' input
            riveParams.setInput("done", value: true)
            
            // Reset after a short delay
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                riveParams.reset()
            }
        }
    }
}

Key Advantage: On iOS and macOS, Rive maintains 60-120 fps without breaking a sweat, freeing up the main CPU for your business logic.

3. Pow: “SwiftUI-first” Magic (Moving Parts)

While Lottie and Rive require external designers (or learning design tools), Pow is a library made by Swift developers for Swift developers. It focuses on transitions and visual effects that feel totally native.

It is ideal for adding “juice” to your application without importing external assets. Everything is code.

Why does the iOS Developer love Pow?

Pow adds View Modifiers that you can chain. Do you want a view to shake when there is an error? Or to appear with an elastic bounce effect? Pow does it in one line.

Example: Change Effects and Transitions

Add Pow via SPM (https://github.com/movingparts-io/Pow).

import SwiftUI
import Pow

struct NotificationView: View {
    @State private var showHeart = false
    @State private var interactionCount = 0
    
    var body: some View {
        VStack(spacing: 40) {
            
            // 1. Change Effect
            // Every time the number changes, it "jumps"
            Text("\(interactionCount)")
                .font(.system(size: 60, weight: .bold))
                .transition(.identity) // Necessary for Pow to take control of redrawing
                .id(interactionCount) // Unique identity per number
                .changeEffect(.spray(origin: .bottom), value: interactionCount)
            
            Button("Increase") {
                interactionCount += 1
            }
            .buttonStyle(.borderedProminent)
            
            Divider()
            
            // 2. Conditional Transitions
            // Much richer than a simple .opacity
            if showHeart {
                Image(systemName: "heart.fill")
                    .resizable()
                    .frame(width: 100, height: 100)
                    .foregroundColor(.red)
                    // "Pop" appearance effect with sparkle
                    .transition(.movingParts.pop(style: .spray))
            }
            
            Button("Toggle Love") {
                withAnimation {
                    showHeart.toggle()
                }
            }
        }
    }
}

Pow is especially useful on watchOS, where resources are limited. Since the animations are geometry-based and not heavy bitmap rendering, it is very friendly to the Apple Watch battery.

4. ConfettiSwiftUI: The Icing on the Cake

Sometimes, you just need to celebrate. Whether the user completed a task, paid for a purchase, or leveled up. Programming a particle system from scratch using CAEmitterLayer in UIKit was tedious; in SwiftUI it was complicated until iOS 17.

ConfettiSwiftUI is a lightweight library specifically for this purpose.

Quick Implementation

SPM URL: https://github.com/simibac/ConfettiSwiftUI

import SwiftUI
import ConfettiSwiftUI

struct CelebrationView: View {
    @State private var counter = 0
    
    var body: some View {
        Button(action: {
            counter += 1
        }) {
            Text("Finish Task!")
                .padding()
                .background(Color.blue)
                .foregroundColor(.white)
                .cornerRadius(10)
        }
        // The confetti emitter anchors to the view
        .confettiCannon(counter: $counter, num: 50, confettis: [.text("🎉"), .text("✨"), .shape(.circle)], openingAngle: Angle(degrees: 0), closingAngle: Angle(degrees: 360), radius: 200)
    }
}

It is simple, effective, and adds that touch of dopamine users love.

Optimization and Performance: Tips for the Expert

As an iOS Developer, integrating libraries isn’t just copy and paste. You must ensure your app flies. Here are pro tips to optimize these animations in Xcode:

1. The .drawingGroup() modifier

If you are animating many native SwiftUI views simultaneously (e.g., 200 particles with Pow), the main thread can get saturated calculating layouts. Use .drawingGroup() at the end of your animated view. This tells SwiftUI: “Stop treating this as individual views, flatten everything into a single texture, and render it using Metal”. Performance will improve dramatically.

2. Watch out for the Main Thread in Lottie

By default, Lottie decodes JSON and renders on the main thread. In very complex animations, this can cause “jank” (stuttering) when scrolling. Configure Lottie to use the Core Animation Rendering Engine (available in recent versions). This delegates work to the system GPU, making the animation as efficient as a native Apple one.

// In the Lottie configuration
let configuration = LottieConfiguration(renderingEngine: .coreAnimation)
// Pass this configuration to your Lottie view

3. watchOS Considerations

On Apple Watch, avoid infinite loop animations (loopMode: .loop) unless they are critical. They drain the battery. Prefer single execution animations (.playOnce) triggered by user actions.

The Future: Native SwiftUI vs. Libraries

It is important to mention that Apple does not stand still. With iOS 17 and later versions, frameworks like PhaseAnimator and KeyframeAnimator have arrived in SwiftUI.

  • PhaseAnimator: Allows animating through a sequence of predefined states (phases), ideal for simple cyclic animations.
  • KeyframeAnimator: Allows granular control like CSS or After Effects, defining values at specific times.

Does this mean the end of libraries? No. Libraries like Rive continue to offer a designer-developer workflow that Xcode does not have. Pow offers pre-packaged effects that would take days to replicate with Keyframes.

Conclusion

Creating a static app is easy. Creating an app that breathes and responds is an art. As an iOS Developer, mastering these tools puts you at a higher level.

  • Use Lottie for complex illustrations and brand assets.
  • Use Rive when you need the animation to be part of the usage mechanics.
  • Use Pow for UI transitions and visual haptic feedback.
  • Use ConfettiSwiftUI to celebrate achievements.

If you have any questions about this article, please contact me and I will be happy to help you 🙂. You can contact me on my X profile or on my Instagram profile.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

How to install Xcode themes

Related Posts