react-native-view-shot icon indicating copy to clipboard operation
react-native-view-shot copied to clipboard

Fabric and ScrollView error

Open rikur opened this issue 6 months ago • 1 comments

[Error: snapshotContentContainer can only be used on a RCTScrollView. instead got: <RCTScrollViewComponentView: 0x158162ed0; frame = (1206 0; 402 653.667); clipsToBounds = YES; tag = 838; layer = <CALayer: 0x60000035aca0>>]

Is anyone using this library with ScrollView and Fabric?

rikur avatar May 16 '25 21:05 rikur

This monkey-patch fixes the issue for me:

diff --git a/ios/RNViewShot.mm b/ios/RNViewShot.mm
index 2cf632fb8dfb09aba637f8c8700fbe02b926404c..1ce9e5a6bf58e9d59772a9c1bc26dd97ff47bfc5 100644
--- a/ios/RNViewShot.mm
+++ b/ios/RNViewShot.mm
@@ -80,10 +80,12 @@ RCT_EXPORT_METHOD(captureRef:(nonnull NSNumber *)target
     UIView* rendered;
     UIScrollView* scrollView;
     if (snapshotContentContainer) {
-      if (![view isKindOfClass:[RCTScrollView class]]) {
-        reject(RCTErrorUnspecified, [NSString stringWithFormat:@"snapshotContentContainer can only be used on a RCTScrollView. instead got: %@", view], nil);
-        return;
-      }
+        NSString *cls = NSStringFromClass([view class]);
+        if ([options[@"snapshotContentContainer"] boolValue] && [cls rangeOfString:@"ScrollView"].location == NSNotFound) {
+            RCTLogError(@"snapshotContentContainer requires a ScrollView-like view.");
+            return;
+        }
+
       RCTScrollView* rctScrollView = view;
       scrollView = rctScrollView.scrollView;
       rendered = scrollView;

rikur avatar May 16 '25 21:05 rikur

or monkey-patch it like this in order to have it working with Nativewind too:

  if (snapshotContentContainer) {
      // find the real UIScrollView under this wrapped view:
      UIScrollView *found = nil;

      // 1) maybe view *is* an RCTScrollView
      if ([view isKindOfClass:[RCTScrollView class]]) {
        found = ((RCTScrollView*)view).scrollView;
      } else {
        // 2) otherwise, walk its subviews to locate one
        for (UIView *sub in view.subviews) {
          if ([sub isKindOfClass:[UIScrollView class]]) {
            found = (UIScrollView*)sub;
            break;
          }
          // also check deeper
          for (UIView *deep in sub.subviews) {
            if ([deep isKindOfClass:[UIScrollView class]]) {
              found = (UIScrollView*)deep;
              break;
            }
          }
          if (found) break;
        }
      }

      if (!found) {
        RCTLogError(@"snapshotContentContainer requires a ScrollView (found %@).", NSStringFromClass(view.class));
        return;
      }

      scrollView = found;
      rendered = scrollView;
    }

makivlach avatar Jun 19 '25 16:06 makivlach