Pular para o conteúdo
charmotion

Como usar o Rive no SwiftUI (iOS)

Por equipe Charmotion · Atualizado em

Ilustração de capa do guia: Como usar Rive no SwiftUI (iOS), com personagens de demonstração do Charmotion

Para usar o Rive no SwiftUI, adicione o pacote Swift RiveRuntime, crie um RiveViewModel com o seu arquivo e o nome da state machine e coloque viewModel.view() na sua view. Esse é o runtime Apple legado, que suporta setInput e triggerInput. O novo runtime Apple controla os arquivos por Data Binding.

Principais pontos

  • Instale o RiveRuntime com Swift Package Manager ou CocoaPods; ele é compatível com iOS 14 ou superior.
  • O runtime Apple novo e o legado vêm no mesmo pacote.
  • As APIs de input (setInput, triggerInput) só funcionam no runtime Apple legado.
  • O novo runtime usa Data Binding, então o arquivo precisa ter view models.

Como instalar o RiveRuntime?

O runtime Apple é o módulo RiveRuntime do repositório rive-app/rive-ios. Ele é distribuído pelo Swift Package Manager e pelo CocoaPods.

Com o Swift Package Manager no Xcode: File → Add Package Dependencies, informe https://github.com/rive-app/rive-ios, escolha uma regra de versão e adicione RiveRuntime ao target do seu app. Com CocoaPods, adicione o pod ao seu Podfile e rode pod install.

Plataformas compatíveis, segundo a documentação do Rive:

  • iOS 14.0+
  • visionOS 1.0+
  • tvOS 16.0+
  • macOS 13.1+
  • Mac Catalyst 14.0+

O runtime adiciona cerca de 1,67 MB ao tamanho do download e cerca de 4,66 MB ao tamanho instalado no iOS (dados do Rive de janeiro de 2026). Cada arquivo .riv incluído no app soma a isso, mas costuma ser pequeno.

Adicione o arquivo .riv ao target do app como qualquer outro recurso. Confira se a opção de target membership está marcada, senão o runtime não vai encontrá-lo ao iniciar.

Qual é a diferença entre o runtime Apple novo e o legado?

O Rive agora distribui duas APIs Apple no mesmo pacote Swift e no mesmo pod, ambas importadas com import RiveRuntime.

Runtime Apple legadoNovo runtime Apple
Tipo principalRiveViewModelData Binding com instâncias de view model
Inputs da state machineCompatível (setInput, triggerInput)Não suportado
Data BindingDisponívelA forma de controlar arquivos
StatusAinda distribuído e documentadoO caminho do Rive para novos projetos

A documentação do Rive é explícita: o recurso de inputs, que foi descontinuado, "só é compatível com o Legacy Runtime, não com o New Runtime". Isso define qual API você vai usar. Se o seu .riv expõe apenas inputs, use o runtime legado. Se ele tem view models, você pode usar o novo runtime.

Para conferir, abra o arquivo no editor do Rive e procure view models no painel de dados, carregue-o no Rive File Inspector gratuito ou pergunte a quem criou o arquivo. O comando Convert Inputs to View Models do editor pode adicionar view models a um arquivo baseado em inputs.

Como exibir um .riv no SwiftUI?

Com o runtime legado, crie um RiveViewModel com o nome do arquivo (sem a extensão) e o nome da state machine, mantenha-o vivo com @StateObject e chame .view() para obter uma view SwiftUI.

import SwiftUI
import RiveRuntime

struct CharacterView: View {
    @StateObject private var character = RiveViewModel(
        fileName: "character",
        stateMachineName: "CharacterStateMachine"
    )

    var body: some View {
        character.view()
            .frame(width: 220, height: 220)
            .accessibilityLabel("Animated character")
    }
}

Mantenha o view model em @StateObject (ou em um objeto pai que seja dono dele) para que ele não seja recriado a cada nova renderização. Recriá-lo reinicia a animação e zera todos os inputs.

Se várias telas mostram o mesmo personagem, dê a cada uma o seu próprio RiveViewModel. Um view model controla uma única view; compartilhá-lo entre duas views visíveis não é compatível com a API legada.

Defina o tamanho da view com .frame. O ajuste padrão mantém a proporção da artboard dentro do frame. Se o personagem transmite algum significado, adicione um rótulo de acessibilidade; se for decorativo, use .accessibilityHidden(true).

Como definir um input numérico ou disparar um trigger?

No runtime legado, o RiveViewModel oferece setInput(_:value:) para booleanos e números (Float ou Double) e triggerInput(_:) para triggers.

struct UploadView: View {
    @StateObject private var character = RiveViewModel(
        fileName: "character",
        stateMachineName: "CharacterStateMachine"
    )

    var body: some View {
        VStack(spacing: 24) {
            character.view().frame(width: 220, height: 220)
            Button("Upload") { Task { await upload() } }
        }
    }

    func upload() async {
        character.setInput("mood", value: 5.0)      // loading loop
        let ok = await performUpload()
        character.triggerInput(ok ? "success" : "error")
        character.setInput("mood", value: 0.0)      // back to idle
    }
}

Como a state machine cuida das transições, seu código continua simples: defina o loop que corresponde ao que o app está fazendo e dispare um trigger quando algo acontecer. Você nunca precisa saber qual animação está na tela no momento.

Os nomes dos inputs diferenciam maiúsculas de minúsculas e precisam ser idênticos aos do arquivo. Disparar um trigger e mudar um número no mesmo instante não é problema, desde que o arquivo esteja configurado para que as reações únicas terminem antes de voltar ao loop atual.

Lembre-se de que essas chamadas fazem parte do sistema de inputs descontinuado e só funcionam no runtime legado da Apple. Elas servem bem para arquivos existentes baseados em inputs; para arquivos novos, considere o Data Binding.

Como usar Data Binding no iOS?

No novo runtime da Apple, você controla um arquivo pela instância do view model dele. Você descreve cada propriedade pelo seu caminho (path) e depois define valores ou dispara triggers na instância:

let mood = NumberProperty(path: "mood")
viewModelInstance.setValue(of: mood, to: 5)

let success = TriggerProperty(path: "success")
viewModelInstance.fire(trigger: success)

No novo runtime, a leitura de valores é assíncrona e usa try await. Consulte a página de Data Binding para Apple na documentação do Rive para saber como obter a instância do view model do seu arquivo e como observar mudanças nas propriedades.

Isso só funciona se o .riv definir um view model com caminhos de propriedade correspondentes. Um arquivo que expõe apenas inputs não tem nada a que essas chamadas possam se vincular.

Os arquivos do Charmotion funcionam com os dois runtimes da Apple. Com o runtime legado, use RiveViewModel em CharacterStateMachine com setInput("mood", value:) e triggerInput(...). Com o novo runtime, crie CharacterViewModelMachine vinculada ao view model Character e use NumberProperty(path: "mood") e TriggerProperty(path: "success"). O conjunto inclui arquivos SwiftUI prontos para as duas opções.

Como respeitar o Reduzir Movimento?

Usuários de iOS podem ativar Ajustes → Acessibilidade → Movimento → Reduzir Movimento. O SwiftUI expõe essa configuração pelo valor de ambiente accessibilityReduceMotion. Leia esse valor e mostre uma imagem estática em vez de um personagem em loop.

struct AdaptiveCharacter: View {
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @StateObject private var character = RiveViewModel(
        fileName: "character",
        stateMachineName: "CharacterStateMachine"
    )

    var body: some View {
        if reduceMotion {
            Image("character-still")
                .resizable()
                .scaledToFit()
                .frame(width: 220, height: 220)
        } else {
            character.view().frame(width: 220, height: 220)
        }
    }
}

O valor de ambiente é atualizado em tempo real, então a view muda se o usuário alterar a configuração com o app aberto. Se a animação comunica um estado, como carregamento ou sucesso, mantenha essa informação disponível por texto ou por um anúncio de acessibilidade, para que nada se perca quando o movimento for removido.

loading: mood 5, fica em loop enquanto o trabalho está em andamento.

Adicione um personagem Rive a um app SwiftUI

  1. Adicione o pacote. No Xcode, adicione https://github.com/rive-app/rive-ios com o Swift Package Manager e vincule RiveRuntime ao seu target.
  2. Inclua o arquivo no app. Arraste o .riv para o projeto e confirme que ele faz parte do target do app.
  3. Escolha o runtime. Use o RiveViewModel legado para arquivos baseados em inputs; use o novo runtime só se o arquivo tiver view models.
  4. Exiba a view. Crie RiveViewModel(fileName:stateMachineName:) em um @StateObject e posicione .view() com um .frame.
  5. Controle os estados. Chame setInput("mood", value: 5.0) para os loops e triggerInput("success") para as reações únicas.
  6. Respeite o Reduzir Movimento. Leia @Environment(\.accessibilityReduceMotion) e mostre uma imagem estática quando o valor for verdadeiro.

Perguntas frequentes

Por que o setInput não faz nada no meu app iOS?

As causas mais comuns são um nome errado de state machine ou de input, ou o uso do novo runtime da Apple, que não é compatível com inputs. Confira os nomes respeitando exatamente maiúsculas, minúsculas e espaços, confirme que você criou um RiveViewModel com stateMachineName e verifique se o view model está guardado em @StateObject em vez de ser recriado.

O Rive funciona com UIKit além de SwiftUI?

Sim. O RiveRuntime é compatível com os dois. No runtime legado, o RiveViewModel pode criar tanto uma view UIKit quanto uma view SwiftUI, e as mesmas chamadas setInput e triggerInput a controlam. A documentação do Rive para Apple explica a configuração do UIKit junto com a do SwiftUI, então você pode usar os dois no mesmo app.

Quais versões do iOS o Rive suporta?

O runtime do Rive para Apple é compatível com iOS 14.0 ou posterior, além de visionOS 1.0+, tvOS 16.0+, macOS 13.1+ e Mac Catalyst 14.0+. Os runtimes novo e legado da Apple vêm no mesmo pacote Swift, então as versões mínimas valem para as duas APIs.

Posso usar um arquivo Rive em um widget ou na launch screen?

Não como animação ao vivo na launch screen (tela de inicialização). As launch screens do iOS são estáticas e configuradas pelo Info.plist ou por um storyboard, sem código personalizado, então reproduza a sua intro em Rive na primeira view real. Os widgets também são renderizados como snapshots, então trate-os como imagens estáticas.

Respostas rápidas deste guia

Fontes

Guias relacionados