Skip to content

Memory leak: ~150MB growth when repeatedly creating/destroying RiveViewModel with enableAutoBind #427

@mfazekas

Description

@mfazekas

Description

When repeatedly creating and destroying RiveViewModel + RiveView with enableAutoBind on a .riv file that has data binding, memory grows ~150MB over 10 cycles and never recovers.

Provide a Repro

Minimal SwiftUI reproduction — toggles a RiveViewModel with enableAutoBind on/off 10 times:

struct MemoryLeakTestView: View {
    @State private var showRive = false
    @State private var cycle = 0
    @State private var running = false

    var body: some View {
        VStack {
            Text("Cycles: \(cycle)")
            if showRive {
                RiveViewWrapper()
                    .frame(height: 200)
            }
            Button("Run 10 Cycles") {
                guard !running else { return }
                running = true
                cycle = 0
                runNextCycle()
            }
        }
    }

    private func runNextCycle() {
        guard cycle < 10 else {
            showRive = false
            running = false
            return
        }
        cycle += 1
        showRive = false
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            showRive = true
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                runNextCycle()
            }
        }
    }
}

private struct RiveViewWrapper: View {
    @StateObject private var vm: RiveViewModel = {
        let vm = RiveViewModel(fileName: "blinko", autoPlay: true)
        vm.riveModel?.enableAutoBind { _ in }
        return vm
    }()
    var body: some View { vm.view() }
}

Steps:

  1. Profile with Instruments → Allocations (Cmd+I)
  2. Tap "Run 10 Cycles"
  3. Observe memory grows ~150MB and never decreases

Source .riv/.rev file

Reproduced with blinko.riv (already in this repo).

Expected behavior

After RiveViewModel is deallocated and SwiftUI destroys the view, memory should return to baseline.

Screenshots

Image

Device & Versions (please complete the following information)

  • Device: iOS Simulator, iPhone 16
  • iOS version: iOS 18.2
  • RiveRuntime: 6.12.1 (SPM)
  • Xcode: 16.2

Additional context

  • Originally discovered in @rive-app/react-native, confirmed in the core rive-ios SDK
  • The leak is deterministic — same cycles always produce the same growth
  • Without enableAutoBind, the leak does not occur

See rive-app/rive-nitro-react-native#167

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions