fix(ios): guard +load with #ifdef RCT_DYNAMIC_FRAMEWORKS#3828
Conversation
kkafar
left a comment
There was a problem hiding this comment.
Hey, this seems sensible. Thank you for the contribution.
I have a remark - as we now have few more components than the one listed here. I'll patch this PR myself in few minutes & land it.
9a567ec to
46fd483
Compare
|
I've failed to confirm that this works, because after usage of Will come back to this in few. |
|
Contacted RNWorklets team and waiting for response. Will come back here once I get it and have time to look at this. |
The +load methods in 12 ComponentView files are unconditional, but their parent RCTViewComponentView correctly guards its +load behind run even when dynamic frameworks are not used, causing conflicts with third-party SDKs (e.g. Akamai BMP) that also use +load — particularly on x86_64 simulators where the load order differs from arm64. This matches the pattern used by React Native core in RCTViewComponentView.mm (see facebook/react-native#37274). Note: UIViewController+RNScreens.mm is intentionally NOT changed as its +load performs method swizzling that is functionally required.
Add guarded +load to 9 ComponentView subclasses (tabs, gamma) that were missing it entirely, which would prevent proper registration when using USE_FRAMEWORKS=dynamic. Normalize all #endif to include the // RCT_DYNAMIC_FRAMEWORKS comment for consistency.
da35f5e to
4d7d84c
Compare
Relocate guarded +load methods to the end of their @implementation blocks under a dedicated "#pragma mark - Dynamic frameworks support" section across all 20 ComponentView files. No behavioral change — purely a code organization refactor for consistency.
kkafar
left a comment
There was a problem hiding this comment.
Looks good. I still have to check the runtime.
There was a problem hiding this comment.
Pull request overview
Guards iOS +load overrides in React Native Screens’ ComponentView implementations behind #ifdef RCT_DYNAMIC_FRAMEWORKS to avoid unintended +load execution in static-linking builds (and the resulting load-order conflicts with third-party SDKs).
Changes:
- Wraps
+ (void)load { [super load]; }with#ifdef RCT_DYNAMIC_FRAMEWORKSacross multiple iOS ComponentView implementations. - Moves previously-unconditional
+loadmethods into a dedicated “Dynamic frameworks support” section near the end of each implementation. - Minor method reordering in some files to keep non-
+loadclass methods (e.g.,componentDescriptorProvider) outside the dynamic-framework guard.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| ios/tabs/screen/RNSTabsScreenComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/tabs/host/RNSTabsHostComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/safe-area/RNSSafeAreaViewComponentView.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/gamma/stack/screen/RNSStackScreenComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/gamma/stack/host/RNSStackHostComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/gamma/split/RNSSplitScreenComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/gamma/split/RNSSplitHostComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/gamma/scroll-view-marker/RNSScrollViewMarkerComponentView.mm | Adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/RNSSearchBar.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenStackHeaderSubview.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenStackHeaderConfig.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenStack.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenNavigationContainer.mm | Guards +load with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenFooter.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenContentWrapper.mm | Guards +load with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreenContainer.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSScreen.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
| ios/RNSModalScreen.mm | Reorders componentDescriptorProvider, adds RCT_DYNAMIC_FRAMEWORKS-guarded +load. |
| ios/RNSFullWindowOverlay.mm | Moves +load and guards it with RCT_DYNAMIC_FRAMEWORKS. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
kkafar
left a comment
There was a problem hiding this comment.
I've checked the runtime in FabricExample. Seems to work fine ✅
Thanks for the PR!
Summary
12 ComponentView files had unconditional
+load { [super load]; }methods, but their parentRCTViewComponentViewcorrectly guards its+loadbehind#ifdef RCT_DYNAMIC_FRAMEWORKS.Without the guard, these
+loadmethods run even when dynamic frameworks are not used, causing conflicts with third-party SDKs (e.g. Akamai BMP) that also use+load— particularly on x86_64 simulators where the load order differs from arm64.This matches the pattern used by React Native core in
RCTViewComponentView.mm(see facebook/react-native#37274).Note:
UIViewController+RNScreens.mmis intentionally NOT changed as its+loadperforms method swizzling that is functionally required.Changes
+loadmethods — wrapped 12 existing unconditional+loadcalls with#ifdef RCT_DYNAMIC_FRAMEWORKS.+loadmethods — 9 additional ComponentView files (gamma, tabs) were missing+loadentirely, which would break component registration when using dynamic frameworks. Added guarded+loadto these files.+loadto end of@implementation— moved all+loadmethods to a dedicated#pragma mark - Dynamic frameworks supportsection just before@endfor consistency and readability.#endifcomments — ensured all#endifdirectives have consistent trailing comments (e.g.#endif // RCT_DYNAMIC_FRAMEWORKS).Affected files
Existing
+loadguarded (12 files):RNSScreen.mmRNSScreenStack.mmRNSScreenContainer.mmRNSScreenNavigationContainer.mmRNSModalScreen.mmRNSFullWindowOverlay.mmRNSScreenFooter.mmRNSSafeAreaViewComponentView.mmRNSSearchBar.mmRNSScreenContentWrapper.mmRNSScreenStackHeaderConfig.mmRNSScreenStackHeaderSubview.mmNew guarded
+loadadded (9 files):RNSScrollViewMarkerComponentView.mmRNSSplitHostComponentView.mmRNSSplitScreenComponentView.mmRNSStackHostComponentView.mmRNSStackScreenComponentView.mmRNSTabsHostComponentView.mmRNSTabsScreenComponentView.mmRNSTabsBottomAccessoryComponentView.mmRNSTabsBottomAccessoryContentComponentView.mmTest plan
USE_FRAMEWORKS=dynamic)+loadmethods are not in the binary (nmcheck)