Skip to content

Commit ef919d1

Browse files
committed
fix(ios): defer fit assignment until MTKView is ready in experimental backend
RiveUIView creates its MTKView lazily during the first layout pass. Setting rive.fit immediately after creating the view had no effect because the drawable didn't exist yet. Store the desired fit as pendingFit and apply it in layoutSubviews once the MTKView is present.
1 parent fb86bf0 commit ef919d1

1 file changed

Lines changed: 21 additions & 7 deletions

File tree

ios/new/RiveReactNativeView.swift

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
@_spi(RiveExperimental) import RiveRuntime
1+
import RiveRuntime
22
import NitroModules
33
import UIKit
4+
import MetalKit
45

56
enum ExperimentalBindData {
67
case none
@@ -27,9 +28,26 @@ class RiveReactNativeView: UIView {
2728
private var isViewReady = false
2829
private var configTask: Task<Void, Never>?
2930
private var isPaused = false
31+
private var pendingFit: RiveRuntime.Fit?
3032

3133
var autoPlay: Bool = true
3234

35+
// Workaround: RiveUIView creates its MTKView lazily during the first
36+
// layout pass, so setting rive.fit immediately after creating the view
37+
// has no effect — the drawable doesn't exist yet. We store the desired
38+
// fit and apply it here once the MTKView is present.
39+
// TODO: Remove once rive-ios handles this internally.
40+
override func layoutSubviews() {
41+
super.layoutSubviews()
42+
if let fit = pendingFit, let rive = riveInstance {
43+
let hasMTKView = riveUIView?.subviews.contains(where: { $0 is MTKView }) ?? false
44+
if hasMTKView {
45+
rive.fit = fit
46+
pendingFit = nil
47+
}
48+
}
49+
}
50+
3351
func awaitViewReady() async -> Bool {
3452
if !isViewReady {
3553
await withCheckedContinuation { continuation in
@@ -93,14 +111,10 @@ class RiveReactNativeView: UIView {
93111

94112
RCTLog("[RiveReactNativeView] Rive instance created successfully")
95113
self.riveInstance = rive
96-
RCTLog("[RiveReactNativeView] Setting up RiveUIView...")
97114
self.setupRiveUIView(with: rive)
98-
RCTLog("[RiveReactNativeView] RiveUIView setup complete")
99115

100-
// Set fit after view is in the hierarchy — passing fit to
101-
// the Rive() constructor breaks .layout mode because the
102-
// MTKView drawable isn't ready yet at construction time.
103-
rive.fit = config.fit
116+
// Defer fit — see layoutSubviews() comment.
117+
self.pendingFit = config.fit
104118

105119
if config.autoPlay {
106120
self.isPaused = false

0 commit comments

Comments
 (0)