refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal#6380
refactor(ios): Migrate from PrivateSentrySDKOnly to SentrySDK.internal#6380alwx wants to merge 3 commits into
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
Plus 2 more 🤖 This preview updates automatically when you update the PR. |
|
@cursor review |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7835dd8. Configure here.
| } | ||
| #else | ||
| @_spi(Private) @objc public static func swizzleRNSScreenViewDidAppear(hook: @escaping () -> Void) {} | ||
| #endif |
There was a problem hiding this comment.
visionOS RNSScreen swizzle skipped
Medium Severity
On visionOS, RNSentryInternal stubs swizzleRNSScreenViewDidAppear and setCurrentScreen, while RNSentry.mm still invokes them under SENTRY_HAS_UIKIT. The prior SentrySwizzle path was not visionOS-gated, so React Navigation frame listening and breadcrumb screen updates can silently no-op on visionOS despite frames APIs being wired for that platform.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7835dd8. Configure here.
Replace the deprecated PrivateSentrySDKOnly SPI and SentrySwizzle.h macro with the new SentrySDK.internal Swift API exposed by sentry-cocoa 9.19.0, via a thin in-pod ObjC<->Swift bridge (RNSentryInternal.swift). Imports Sentry with @_spi(Private) for SPI-gated sub-APIs (performance, replay, envelope). Drops the performSelector workaround around getReplayIntegration since SentrySDK.internal.replay.capture() returns Bool directly. Closes #6370 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Move RNSentryStartTests, RNSentryStartFromFileTests, and RNSentryReplayOptionsTests
to SentrySDK.internal.{options, options(fromDictionary:), appStart.hybridSDKMode,
performance.framesTrackingHybridSDKMode}.
The ObjC RNSentryTests.m keeps PrivateSentrySDKOnly for now — the test target
is a separate consumer of the RNSentry static-lib pod and cannot see
RNSentry-Swift.h without modulemap surgery. Worth revisiting when sentry-cocoa
removes PrivateSentrySDKOnly in the next major.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`SentryInternalSwizzleApi` in sentry-cocoa has no platform gating, and `SENTRY_HAS_UIKIT` (which guards the `[RNSentryRNSScreen swizzleViewDidAppear]` call in RNSentry.mm) covers visionOS. The Swift bridge was gated to `iOS/tvOS/macCatalyst` only, silently no-oping the swizzle on visionOS where the deprecated `SentrySwizzle` macro used to work. Also documents why `setCurrentScreen` remains a visionOS no-op: sentry-cocoa's `SentryInternalScreenApi` is intentionally gated to iOS/tvOS, so the new API surface itself doesn't expose the setter on visionOS. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
b850f46 to
330236b
Compare
📲 Install BuildsAndroid
|
iOS (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 3d377b5+dirty | 1218.48 ms | 1219.51 ms | 1.03 ms |
| a50b33d+dirty | 1197.74 ms | 1197.17 ms | -0.57 ms |
| 4b87b12+dirty | 1212.90 ms | 1222.09 ms | 9.19 ms |
| ef27341+dirty | 3856.13 ms | 1231.42 ms | -2624.71 ms |
| 68ae91b+dirty | 3834.04 ms | 1216.60 ms | -2617.44 ms |
| ae37560+dirty | 3832.10 ms | 1219.09 ms | -2613.02 ms |
| f170ec3+dirty | 3822.26 ms | 1218.33 ms | -2603.93 ms |
| 0a147b2+dirty | 3838.15 ms | 1221.94 ms | -2616.21 ms |
| 0bd8916+dirty | 3842.33 ms | 1230.76 ms | -2611.58 ms |
| 1e5d96d+dirty | 3851.45 ms | 1212.05 ms | -2639.41 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 3d377b5+dirty | 3.38 MiB | 4.76 MiB | 1.38 MiB |
| a50b33d+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 4b87b12+dirty | 3.38 MiB | 4.77 MiB | 1.39 MiB |
| ef27341+dirty | 5.15 MiB | 6.68 MiB | 1.53 MiB |
| 68ae91b+dirty | 4.98 MiB | 6.46 MiB | 1.48 MiB |
| ae37560+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
| f170ec3+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 0a147b2+dirty | 4.98 MiB | 6.51 MiB | 1.53 MiB |
| 0bd8916+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 1e5d96d+dirty | 4.98 MiB | 6.46 MiB | 1.49 MiB |
iOS (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 2363c0f+dirty | 3834.61 ms | 1224.46 ms | -2610.15 ms |
| a50b33d+dirty | 1207.11 ms | 1212.10 ms | 5.00 ms |
| 0d9949d+dirty | 1203.94 ms | 1202.27 ms | -1.67 ms |
| 5ee78d6+dirty | 3815.71 ms | 1217.04 ms | -2598.67 ms |
| 100ce80+dirty | 3843.57 ms | 1226.46 ms | -2617.12 ms |
| 0a147b2+dirty | 3845.11 ms | 1230.81 ms | -2614.30 ms |
| 6176a94+dirty | 3854.15 ms | 1221.77 ms | -2632.38 ms |
| bc0d8cf+dirty | 3834.64 ms | 1223.91 ms | -2610.73 ms |
| 5fe1c6c+dirty | 1201.36 ms | 1209.15 ms | 7.78 ms |
| 37a2091+dirty | 3865.27 ms | 1223.92 ms | -2641.35 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 2363c0f+dirty | 4.98 MiB | 6.46 MiB | 1.49 MiB |
| a50b33d+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 0d9949d+dirty | 3.38 MiB | 4.76 MiB | 1.38 MiB |
| 5ee78d6+dirty | 5.15 MiB | 6.69 MiB | 1.53 MiB |
| 100ce80+dirty | 5.15 MiB | 6.67 MiB | 1.51 MiB |
| 0a147b2+dirty | 4.98 MiB | 6.51 MiB | 1.53 MiB |
| 6176a94+dirty | 5.15 MiB | 6.68 MiB | 1.53 MiB |
| bc0d8cf+dirty | 5.15 MiB | 6.67 MiB | 1.51 MiB |
| 5fe1c6c+dirty | 3.38 MiB | 4.77 MiB | 1.39 MiB |
| 37a2091+dirty | 5.15 MiB | 6.70 MiB | 1.54 MiB |
antonis
left a comment
There was a problem hiding this comment.
Overall looks good. I think a conditional import like should fix the build issues 🤞
#if __has_include(<RNSentry/RNSentry-Swift.h>)
#import <RNSentry/RNSentry-Swift.h>
#else
#import "RNSentry-Swift.h"
#endif


📢 Type of change
📜 Description
Replace deprecated
PrivateSentrySDKOnlySPI andSentrySwizzle.hmacro usage in our iOS code with the newSentrySDK.internalSwift API exposed by sentry-cocoa 9.19.0, via a thin in-pod ObjC↔Swift bridge (RNSentryInternal.swift).The bridge uses
@_spi(Private) import Sentryto reach SPI-gated sub-APIs (performance.currentScreenFrames,replay.configure,envelope.{store,capture,deserialize}). Existing.m/.mmcallers route through[RNSentryInternal …]via the auto-generatedRNSentry-Swift.h. TheperformSelector:@selector(getReplayIntegration)workaround incaptureReplayWithReturnValueis gone —SentrySDK.internal.replay.capture()returnsBooldirectly.Notably, we do not use sentry-cocoa's new
SentryObjCumbrella module (which the issue suggested) — that module isn't shipped via theSentryCocoaPod in 9.19.0, only via SPM as a separate xcframework. The Swift bridge works equally on both consumption paths.💡 Motivation and Context
Closes #6370.
PrivateSentrySDKOnlyis deprecated in sentry-cocoa 9.19.0 and slated for removal in the next major. Migrating now avoids future churn and drops the private header search path /performSelector:reliance.💚 How did you test it?
yarn build,yarn test,yarn lint,yarn circularDepCheck— all greenxcodebuildfor theRNSentrypod target (iphonesimulator) — builds cleanxcodebuild testforRNSentryCocoaTester— 158/158 native Cocoa tests pass📝 Checklist
sendDefaultPIIis enabled🔮 Next steps