Skip to content

Commit 44681b5

Browse files
committed
fix: implement color property get/listen and fix UInt32 crash on experimental iOS
Color.argbValue is now public in rive-ios 6.15.2 — implement getValue via blockingAsync, addListener via valueStream, and fix setter crash by using UInt32(bitPattern:) for negative ARGB values from JS.
1 parent 651f09a commit 44681b5

File tree

2 files changed

+84
-8
lines changed

2 files changed

+84
-8
lines changed

docs/riv-files.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# .riv File Catalog
2+
3+
Properties of all .riv files used in this project.
4+
5+
**Legend**: SM = State Machine, DB = Data Binding, AP = Auto-play, OOB = Out-of-band assets
6+
7+
## Local Files (`example/assets/rive/`)
8+
9+
| File | SM | DB | AP | Notes |
10+
|------|----|----|-----|-------|
11+
| `quick_start.riv` | Yes | Yes | Yes | Artboard: `health_bar_v01`. VM props: `health` (number), `gameOver` (trigger). Game health/damage system. |
12+
| `databinding.riv` | Yes | Yes | Yes | Primary data binding test file. `Person` VM with: `age` (number), `name` (string), `likes_popcorn` (bool), `favourite_color` (color), `favourite_pet` (enum), `jump` (trigger). Nested `pet` VM. Enum `Pets`: dog/cat/frog/owl/chipmunk/rat. 2 view models total. |
13+
| `databinding_lists.riv` | Yes | Yes | - | `DevRel` VM with `team` list property. Default 5 items. Tests list mutations. **Experimental crash**: list mutations (removeInstanceAt, swap, addInstanceAt) cause EXC_BAD_ACCESS. |
14+
| `databinding_images.riv` | Yes | Yes | - | `MyViewModel` with `bound_image` image property. **Experimental crash**: EXC_BAD_ACCESS on load. |
15+
| `artboard_db_test.riv` | Yes | Yes | - | Multiple artboards, artboard properties: `artboard_1`, `artboard_2`. **Experimental crash**: EXC_BAD_ACCESS on load. |
16+
| `viewmodelproperty.riv` | Yes | Yes | - | Complex nested VMs: `vm1`/`vm2` instances with nested `pet` VM. Tests replaceViewModel(). |
17+
| `rewards.riv` | Yes | Yes | Yes | Bouncing chest animation by default. Nested property paths: `Coin/Item_Value` (number), `Button/State_1` (string), `Energy_Bar/Bar_Color` (color), `Button/Pressed` (trigger). Works with experimental runtime. |
18+
| `many_viewmodels.riv` | Yes | Yes | - | Named instances: `red`, `green`, `blue`. Image property: `imageValue`. |
19+
| `rating.riv` | Yes | No | No | Static 5-star selector — no auto-play animation, only responds to SM number input: `rating` (0-5). |
20+
| `out_of_band.riv` | Yes | No | - | SM: `State Machine 1`. OOB image (`referenced-image-2929282`), font (`Inter-594377`), audio (`referenced_audio-2929340`). |
21+
| `hello_world_text.riv` | Yes | No | Yes | Text run: `name`. Simple text animation. |
22+
| `click-count.riv` | Yes | No | - | Click counter with pointer events/listeners. |
23+
| `blinko.riv` | Yes | Yes | - | Uses Rive Scripting. DataBindMode.Auto. |
24+
| `layouts_demo.riv` | Yes | No | Yes | Tests Fit.Layout and layoutScaleFactor. |
25+
| `ios_android_layouts_demo_v01.riv` | Yes | No | - | Platform-specific layout testing. |
26+
| `movecircle.riv` | Yes | No | Yes | Simple moving circle animation. |
27+
| `bouncing_ball.riv` | Yes | No | Yes | Physics-based bouncing ball. |
28+
| `font_fallback.riv` | Yes | No | - | Tests font fallback behavior. |
29+
| `arbtboards-models-instances.riv` | Yes | Yes | - | Multiple artboards. Tests artboard/model/instance enumeration. |
30+
31+
## External Files (`example/assets/` root)
32+
33+
| File | SM | DB | AP | Notes |
34+
|------|----|----|-----|-------|
35+
| `lists_demo.riv` | Yes | Yes | - | `DevRel` VM with list. `listItem` VM: `label`, `hoverColor`, `fontIcon`. Menu/list UI demo. |
36+
| `swap_character_main.riv` | Yes | Yes | - | SM: `State Machine 1`. `Card` VM with artboard property `CharacterArtboard`. Artboards: `Main`, `Placeholder`. |
37+
| `swap_character_assets.riv` | No | No | - | External asset file only. Artboards: `Character 1` (Dragon), `Character 2` (Gator). No SM needed. |
38+
39+
## Remote Files (CDN)
40+
41+
| URL | SM | DB | AP | Notes |
42+
|-----|----|----|-----|-------|
43+
| `cdn.rive.app/animations/vehicles.riv` | **No** | No | Yes | Endless looping vehicle parade. No state machine, no interactivity. **Does not work with experimental iOS runtime** (requires SM). |
44+
| `cdn.rive.app/animations/off_road_car_v7.riv` | **No** | No | Yes | Off-road car with idle/bouncing/windshield_wipers timeline animations. No state machine. **Does not work with experimental iOS runtime**. |
45+
46+
## Experimental Backend Compatibility
47+
48+
Files that **crash** the experimental backend:
49+
- `databinding_images.riv` - EXC_BAD_ACCESS on load
50+
- `artboard_db_test.riv` - EXC_BAD_ACCESS on load
51+
- `databinding_lists.riv` - list mutation operations crash
52+
53+
Files that **don't work** with experimental backend:
54+
- `vehicles.riv` (remote) - no state machine, experimental API requires one
55+
- `swap_character_assets.riv` - no state machine (asset-only file)

ios/new/HybridViewModelColorProperty.swift

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ class HybridViewModelColorProperty: HybridViewModelColorPropertySpec {
66
private let prop: ColorProperty
77
private var listenerTasks: [UUID: Task<Void, Never>] = [:]
88

9-
// Note: Color.argbValue is internal in rive-ios, so get value throws.
10-
// setValue() works, but reading colors back is not possible.
11-
// TODO: File issue with rive-ios to expose Color.argbValue in SPI
12-
139
init(instance: ViewModelInstance, path: String) {
1410
self.instance = instance
1511
self.prop = ColorProperty(path: path)
@@ -18,11 +14,16 @@ class HybridViewModelColorProperty: HybridViewModelColorPropertySpec {
1814

1915
var value: Double {
2016
get {
21-
RCTLogError("[ColorProperty] getValue not supported - rive-ios Color.argbValue is internal")
22-
return 0
17+
do {
18+
let color = try blockingAsync { try await self.instance.value(of: self.prop) }
19+
return Double(color.argbValue)
20+
} catch {
21+
RCTLogError("[ColorProperty] getValue failed: \(error)")
22+
return 0
23+
}
2324
}
2425
set {
25-
let color = Color(UInt32(newValue))
26+
let color = Color(UInt32(bitPattern: Int32(newValue)))
2627
let inst = instance
2728
let p = prop
2829
Task { @MainActor in
@@ -32,7 +33,27 @@ class HybridViewModelColorProperty: HybridViewModelColorPropertySpec {
3233
}
3334

3435
func addListener(onChanged: @escaping (Double) -> Void) throws -> () -> Void {
35-
throw RuntimeError.error(withMessage: "Color addListener() not supported - rive-ios Color.argbValue is internal")
36+
let id = UUID()
37+
let task = Task { @MainActor [weak self] in
38+
guard let self else { return }
39+
while !Task.isCancelled {
40+
let stream = self.instance.valueStream(of: self.prop)
41+
do {
42+
for try await color in stream {
43+
onChanged(Double(color.argbValue))
44+
}
45+
break
46+
} catch {
47+
RCTLogWarn("[ColorProperty] listener stream interrupted: \(error), restarting")
48+
try? await Task.sleep(nanoseconds: 100_000_000)
49+
}
50+
}
51+
}
52+
listenerTasks[id] = task
53+
return { [weak self] in
54+
self?.listenerTasks[id]?.cancel()
55+
self?.listenerTasks.removeValue(forKey: id)
56+
}
3657
}
3758

3859
func removeListeners() throws {

0 commit comments

Comments
 (0)