[iOS] Script init caches the wrong view model when dataBind is applied after state-machine creation

Cerrado Apto para principiantes
#414 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Ya se ha fusionado un pull request relacionado.

  • #415 de @mfazekas — fusionado
  • #421 de @rive-engineering — fusionado

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
63/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
react-native, swift, typescript
Área
backend, mobile

Línea de trabajo

Lee ios/new/RiveReactNativeView.swift, centrándote en la creación de la máquina de estados y la resolución de dataBind. Compara el orden actual con la sonda Swift independiente proporcionada y el diff propuesto; después, ejecuta la reproducción en iOS con RiveRuntime 6.28.0. Se considera terminado cuando se usa la instancia host vinculada explícitamente al crear la máquina de estados, de modo que la sonda informe isReady: 1 y observedSeed: 42; Android y el backend heredado quedan fuera de la validación reportada.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug iOS

Description

On the iOS new runtime, supplying an explicit view-model instance through <RiveView dataBind={instance}> can leave a Luau script reading and writing the authored default instance instead of the host instance.

The script caches context:viewModel() in init. The React Native wrapper creates the state machine before passing the explicit instance into Rive(...dataBind: .instance(...)). The script appears to initialize against the default instance during state-machine creation and retain that reference after the host model is bound.

This has a functional consequence beyond the deprecated-API warnings tracked in #403: host initialization values are invisible to the script, and script-written readiness/results never reach the host's instance. In a small probe, the host seeds seed = 42, the script sets isReady = 1 in init, and each advance copies its cached model's seed into observedSeed.

Value read from the host instance after 2 seconds Current order Bind at state-machine creation Expected
seed 42 42 42
isReady 0 1 1
observedSeed 0 42 42

The current-order rectangle renders red (script sees seed 0), while the early-binding rectangle renders green (script sees seed 42). There is no crash or script exception.

Minimal reproduction and source file

Complete standalone reproduction

The gist includes:

  • A 17,434-byte signed .riv fixture, base64-encoded because gists do not accept binary files, with a decode command and SHA-256 checksum. No CLI login is required to run the supplied file.
  • Complete scene.rml, probe.luau, and rive.yaml source: one artboard, one state machine, one script, three numbers; no application assets.
  • A runnable main.swift + run-ios.py probe that tests both initialization orders side by side using RiveRuntime 6.28.0. It prints results and asserts both outcomes.
  • Actual results.json, a minimal React Native App.tsx adapter, and proposed-fix.diff.
Verified native repro steps
  1. Clone/download the gist and decode binding-init-repro.riv.b64 using the command in its README.
  2. Download the official RiveRuntime 6.28.0 XCFramework.
  3. With an Apple Silicon iOS simulator booted, run python3 run-ios.py /path/to/RiveRuntime.xcframework.
  4. Observe lateBinding: {seed: 42, isReady: 0, observedSeed: 0} and bindingAtCreation: {seed: 42, isReady: 1, observedSeed: 42}.

Both cases create independent artboards and host model instances from the same file. Both seed the model before state-machine creation and use the same deprecated Rive(...dataBind: .instance(model)) initializer afterward. The only difference is supplying binding: model to createStateMachine.

React Native usage

The App.tsx adapter uses useViewModelInstance(riveFile, { async: true, viewModelName: 'ProbeModel', onInit }), seeds seed = 42 in onInit, and mounts RiveView only after the instance exists:

<RiveView
  file={riveFile}
  artboardName="Binding Probe"
  stateMachineName="Main"
  dataBind={instance}
  autoPlay
  fit={Fit.Layout}
  style={{ width: 160, height: 160 }}
/>

Use a native development build, add riv to Metro's assetExts, and leave the default iOS new backend enabled. The gist has the complete component and setup notes.

Likely cause / small workaround

The relevant current code is in ios/new/RiveReactNativeView.swift at v0.5.4. It calls createStateMachine(config.stateMachineName) before resolving dataBind and constructing Rive.

Moving state-machine creation after binding resolution and using the explicit-instance overload fixes the isolated probe:

let stateMachine: StateMachine
if case .instance(let vmi) = dataBind {
  stateMachine = try await artboard.createStateMachine(
    config.stateMachineName, binding: vmi
  )
} else {
  stateMachine = try await artboard.createStateMachine(config.stateMachineName)
}

The Rive iOS 6.28.0 release guidance also supplies the model at state-machine creation. The attached diff is a narrow workaround for initial explicit-instance binding, not a complete migration or a claim to fix later instance replacement. The broader auto/by-name/rebinding migration can stay under #403.

Environment / validation scope

  • Original affected application: @rive-app/react-native 0.5.3, React Native 0.86.0, Expo SDK 57, react-native-nitro-modules 0.36.5.
  • Runtime: iOS new backend, RiveRuntime 6.28.0.
  • Standalone Swift repro actually executed on iPhone 17 Pro simulator, iOS 26.5; recorded results are in the gist.
  • Latest 0.5.4 source inspected: the relevant initialization order is unchanged and its runtimeVersions.ios is also 6.28.0. I have not separately run a complete 0.5.4 React Native app.
  • The generic App.tsx adapter type-checks against 0.5.3; the executed isolated test is the Swift probe, which follows the wrapper's native initialization sequence.
  • Android and the legacy iOS backend: not tested for this issue.
  • Previous working version: not established.
  • Fixture authored with Rive CLI 1.3.0, signed and watermarked. It executes in both native cases, so this is not an unsigned-script rejection.

I searched existing issues and found #403 related, but did not find a report for this specific cached-script-model behavior. Happy to consolidate this reproduction into #403 if that is preferable.

Lenguaje dominante
TypeScript
Estrellas
157
Forks
16
Merge medio
4 d 9 h
PR fusionados (30 d)
21

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de rive-app/rive-nitro-react-native

Todos los issues de rive-app/rive-nitro-react-native

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.