Skip to content

fix(ios): bind the view model at state machine creation, including DataBindMode.Auto - #420

Merged
mfazekas merged 3 commits into
rive-app:mainfrom
kirgy:fix/ios-bind-vmi-at-state-machine-creation
Oct 13, 2026
Merged

mfazekas merged 3 commits into
rive-app:mainfrom
kirgy:fix/ios-bind-vmi-at-state-machine-creation

Conversation

@kirgy

@kirgy kirgy commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

The follow is an AI assisted summary of this change. TLDR;

  • PR 415 covers the non-auto path of Luau script databinding
  • this fixes the auto path, and has been tested locally to resolve it

Complements #415: also binds the instance at state-machine creation for DataBindMode.Auto, which #415 leaves to #403.

On the new iOS backend, artboards that use scripts read and write the wrong view model instance. The state machine is created unbound and the instance is attached afterwards, but scripts run init (and cache context:viewModel()) during state machine creation. This is upstream #414.

  • Resolve the binding instance first: .auto → the artboard's default instance, .byName, or an explicit .instance
  • Create the state machine with createStateMachine(name, binding:) and build Rive with that same instance

Reproduction

We reproduced this with a company private Rive asset. We're happy to pass this over privately to support you with this. I've given the .riv and .rev files via our support Slack.

Repro page against a scripted production asset (ZOE's home progress bar, progress_bar.riv), kept in example/src/reproducers/local/ because the asset is proprietary. The bar's scripts read startValue / newValue / trackWidth and write renderedPercent / _fillWidth / barTransitionState. iOS 26.5 simulator, Release build.

0.5.4 this branch
renderedPercent after newValue = 5.8 + play 0.0 (script never sees the write) 6.0
trackWidth (script-computed) 304 (authored default) 279
Visual at low fill track stops short of the end cap track meets the end cap, matching Android
newValue = 100, instance bound before mount gradient fallback, barState = default barState = complete (green, crown celebration)

The stalled fill was rive-ios 6.28.0, fixed in 6.28.1

With this binding fix on RiveRuntime 6.28.0, firing play on a running state machine left the scripted fill stuck (barTransitionState = increasing, renderedPercent frozen). To rule out this wrapper, I ran the same sequence against RiveRuntime directly in a native Swift harness on the simulator, with no React Native involved, and headlessly on the web runtime (@rive-app/canvas 2.39):

play on a running state machine, instance bound at creation Result
Web runtime fill animates 6 → 30 in about 1.5 s, settles
RiveRuntime 6.28.0 (native) stuck at 6, never settles
RiveRuntime 6.28.1 (native) animates 6 → 29 → 30, settles
RiveRuntime 6.28.0, unbound until after creation (current wrapper order) scripts never react

6.28.1's notes include "Fixed asynchronous image decodes not completing and animations stopping while script work was still pending". With this branch plus RiveRuntime 6.28.1 (via RIVE_RUNTIME_IOS_VERSION=6.28.1 and a local podspec), the RN repro behaves correctly in the app's real order (auto-bind, read the instance off the view ref, then play): 5.8 settles with the track meeting the end cap, 30 animates and settles, and 100 reaches the complete state.

So the full fix needs both:

  1. this change (bind at state machine creation), and
  2. RiveRuntime ≥ 6.28.1. On 2026-10-13 that's a GitHub release / SPM only, not yet on CocoaPods trunk (the newest there is 6.28.0), so runtimeVersions.ios can't be bumped yet.

One behaviour change to flag upstream: on 6.28.1, a trigger fired on the instance before the state machine exists (bound at creation) no longer applies. The fill sits at its minimum, where on 6.28.0 it jumped straight to the target. Natively the same thing happens, so it's a runtime change, not this wrapper.

@kirgy
kirgy marked this pull request as ready for review October 13, 2026 13:33
@mfazekas
mfazekas force-pushed the fix/ios-bind-vmi-at-state-machine-creation branch from a3983ca to d901c06 Compare October 13, 2026 18:57

@mfazekas mfazekas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified on the iOS simulator: explicit instance, Auto and byName now all bind before the state machine is created, so scripts see the right instance. Rebased onto main and dropped #415's now-redundant explicit-instance block so it compiles, and added Auto and byName cases to the script data-binding harness test.

@mfazekas
mfazekas enabled auto-merge (squash) October 13, 2026 19:08
kirgy and others added 3 commits October 13, 2026 21:36
Scripts run init during state machine creation and cache
context:viewModel(). The new iOS backend created the state machine
unbound and attached the instance afterwards through Rive(dataBind:),
so scripted artboards read and wrote the authored default instance
instead of the one the app binds (rive-app#414). Resolve the instance first
(auto, by name or explicit) and pass it to createStateMachine(binding:).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mfazekas
mfazekas force-pushed the fix/ios-bind-vmi-at-state-machine-creation branch from d901c06 to 8a6016d Compare October 13, 2026 19:36
@mfazekas
mfazekas merged commit d606620 into rive-app:main Oct 13, 2026
15 checks passed
mfazekas pushed a commit that referenced this pull request Oct 13, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.5.5](v0.5.4...v0.5.5)
(2026-10-13)


### Bug Fixes

* don't call into a disposed list property when useRiveList unmounts
([#408](#408))
([bfa7aab](bfa7aab)),
closes
[#407](#407)
* **ios:** bind the view model at state machine creation, including
DataBindMode.Auto
([#420](#420))
([d606620](d606620))
* **ios:** bind the view model instance when creating the state machine
([#415](#415))
([d49a09a](d49a09a)),
closes
[#414](#414)
* **ios:** bump rive-ios to 6.28.1
([#422](#422))
([628e5d5](628e5d5))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
@mfazekas

Copy link
Copy Markdown
Collaborator

Thanks Kirgy! Shipped in v0.5.5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants