Skip to main content

Quick Start Guide

This guide will walk you through creating your first Rive animation in an iOS app, from installation to rendering an interactive animation on screen.

Prerequisites

Before starting, ensure you have:
  • Xcode 14.0 or later installed
  • An iOS project targeting iOS 14.0+ (or macOS 13.1+, tvOS 16.0+, visionOS 1.0+)
  • The RiveRuntime package installed (see Installation Guide)

Step 1: Add a Rive File to Your Project

1

Get a Rive File

Download a .riv file from the Rive Community or create your own in the Rive Editor.For this guide, we’ll use a file named truck.riv.
2

Add to Xcode Project

Drag the .riv file into your Xcode project navigator. Make sure to:
  • Check Copy items if needed
  • Select your app target in Add to targets
3

Verify Resource

The file should now appear in your target’s Build Phases → Copy Bundle Resources.

Step 2: Import RiveRuntime

At the top of your Swift file, import the RiveRuntime framework:
import RiveRuntime
import SwiftUI // or UIKit

Step 3: Create Your First Animation

Choose the approach that matches your app architecture:
import SwiftUI
import RiveRuntime

struct ContentView: View {
    @StateObject private var viewModel = RiveViewModel(
        fileName: "truck"
    )
    
    var body: some View {
        viewModel.view()
            .aspectRatio(contentMode: .fit)
    }
}
By default, RiveViewModel automatically plays the first animation in the file. You can customize this behavior with additional parameters.

Step 4: Customize Playback Options

Control animation playback, layout, and loop behavior:
Customization Options
@StateObject private var viewModel = RiveViewModel(
    fileName: "truck",
    animationName: "drive",      // Specific animation to play
    artboardName: "Artboard",     // Specific artboard (optional)
    fit: .contain,                 // How the animation fits in the view
    alignment: .center,            // Alignment within the view
    autoPlay: true,                // Start playing automatically
    loop: .loop                    // Loop behavior (.loop, .oneShot, .pingPong)
)

Layout Options

Control how your animation fits within its container:
Layout Configuration
import SwiftUI
import RiveRuntime

struct LayoutExample: View {
    @StateObject private var viewModel = RiveViewModel(
        fileName: "layout_test",
        fit: .contain
    )
    
    @State private var fit: RiveFit = .contain
    @State private var alignment: RiveAlignment = .center
    
    var body: some View {
        VStack {
            viewModel.view()
                .onChange(of: fit) { newValue in
                    viewModel.fit = newValue
                }
                .onChange(of: alignment) { newValue in
                    viewModel.alignment = newValue
                }
            
            // Layout controls
            HStack {
                Button("Fill") { fit = .fill }
                Button("Contain") { fit = .contain }
                Button("Cover") { fit = .cover }
                Button("Fit Width") { fit = .fitWidth }
            }
            
            HStack {
                Button("Top Left") { alignment = .topLeft }
                Button("Center") { alignment = .center }
                Button("Bottom Right") { alignment = .bottomRight }
            }
        }
    }
}

Step 5: Add Interactivity with State Machines

State machines make your animations interactive by responding to user input:
State Machine Example
import SwiftUI
import RiveRuntime

struct InteractiveAnimation: View {
    @StateObject private var viewModel = RiveViewModel(
        fileName: "skills",
        stateMachineName: "Designer's Test"
    )
    
    var body: some View {
        VStack {
            viewModel.view()
                .frame(height: 200)
            
            HStack {
                Button("Beginner") {
                    viewModel.setInput("Level", value: 0.0)
                }
                Button("Intermediate") {
                    viewModel.setInput("Level", value: 1.0)
                }
                Button("Expert") {
                    viewModel.setInput("Level", value: 2.0)
                }
            }
            .padding()
        }
    }
}

Input Types

State machines support three types of inputs:
// Set a numeric input
viewModel.setInput("Level", value: 2.0)

Step 6: Display Multiple Animations

You can display different artboards and animations from the same Rive file:
Multiple Animations
import SwiftUI
import RiveRuntime

struct MultipleAnimationsView: View {
    let file = try! RiveFile(name: "artboard_animations")
    
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                Text("Square - Go Around")
                RiveViewModel(
                    model(file: file),
                    animationName: "goaround",
                    artboardName: "Square"
                ).view()
                .aspectRatio(1, contentMode: .fit)
                
                Text("Square - Roll Around")
                RiveViewModel(
                    model(file: file),
                    animationName: "rollaround",
                    artboardName: "Square"
                ).view()
                .aspectRatio(1, contentMode: .fit)
                
                Text("Circle")
                RiveViewModel(
                    model(file: file),
                    artboardName: "Circle"
                ).view()
                .aspectRatio(1, contentMode: .fit)
            }
            .padding()
        }
    }
    
    func model(file: RiveFile) -> RiveModel {
        RiveModel(riveFile: file)
    }
}

Complete Working Example

Here’s a complete example that puts it all together:
Complete Example
import SwiftUI
import RiveRuntime

struct RiveAnimationView: View {
    @StateObject private var viewModel = RiveViewModel(
        fileName: "halloween",
        autoPlay: false
    )
    
    @State private var isPlaying = false
    
    var body: some View {
        VStack {
            // Animation View
            viewModel.view()
                .aspectRatio(contentMode: .fit)
                .frame(height: 300)
            
            // Playback Controls
            HStack(spacing: 20) {
                Button(action: togglePlayback) {
                    Image(systemName: isPlaying ? "pause.fill" : "play.fill")
                        .font(.title)
                }
                
                Button("Reset") {
                    viewModel.reset()
                    isPlaying = false
                }
            }
            .padding()
        }
        .padding()
    }
    
    private func togglePlayback() {
        if isPlaying {
            viewModel.pause()
        } else {
            viewModel.play()
        }
        isPlaying.toggle()
    }
}

#Preview {
    RiveAnimationView()
}

Common RiveViewModel Methods

// Play the animation
viewModel.play()

// Pause the animation
viewModel.pause()

// Stop and reset to the beginning
viewModel.stop()

// Reset to initial state
viewModel.reset()

Next Steps

Now that you’ve created your first Rive animation, explore more advanced features:

Animation Playback

Learn about advanced playback control and animation management

State Machines

Create complex interactive animations with state machines

Layout

Master layout options, fit modes, and alignment

Events

Listen and respond to events from your animations

Troubleshooting

Animation Not Showing

  • Verify the .riv file is in your bundle resources
  • Check the file name matches exactly (case-sensitive)
  • Ensure the view has a non-zero frame size

Animation Not Playing

  • Check that autoPlay is set to true or call viewModel.play() explicitly
  • Verify the animation name exists in your Rive file
  • Make sure the artboard name is correct if specified

State Machine Inputs Not Working

  • Verify the state machine name is correct
  • Check that input names match exactly (case-sensitive)
  • Ensure the input type matches (number, boolean, or trigger)
  • Confirm the state machine is properly configured in the Rive editor

Resources

Build docs developers (and LLMs) love