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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions