Skip to content

fix(ios): guard +load with #ifdef RCT_DYNAMIC_FRAMEWORKS#3828

Merged
kkafar merged 3 commits intosoftware-mansion:mainfrom
DavidDuarte22:fix/guard-load-with-dynamic-frameworks
Apr 15, 2026
Merged

fix(ios): guard +load with #ifdef RCT_DYNAMIC_FRAMEWORKS#3828
kkafar merged 3 commits intosoftware-mansion:mainfrom
DavidDuarte22:fix/guard-load-with-dynamic-frameworks

Conversation

@DavidDuarte22
Copy link
Copy Markdown
Contributor

@DavidDuarte22 DavidDuarte22 commented Mar 31, 2026

Summary

12 ComponentView files had unconditional +load { [super load]; } methods, but their parent RCTViewComponentView correctly guards its +load behind #ifdef RCT_DYNAMIC_FRAMEWORKS.

Without the guard, these +load methods 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.

Changes

  1. Guarded existing +load methods — wrapped 12 existing unconditional +load calls with #ifdef RCT_DYNAMIC_FRAMEWORKS.
  2. Added missing guarded +load methods — 9 additional ComponentView files (gamma, tabs) were missing +load entirely, which would break component registration when using dynamic frameworks. Added guarded +load to these files.
  3. Relocated +load to end of @implementation — moved all +load methods to a dedicated #pragma mark - Dynamic frameworks support section just before @end for consistency and readability.
  4. Normalized #endif comments — ensured all #endif directives have consistent trailing comments (e.g. #endif // RCT_DYNAMIC_FRAMEWORKS).

Affected files

Existing +load guarded (12 files):

  • RNSScreen.mm
  • RNSScreenStack.mm
  • RNSScreenContainer.mm
  • RNSScreenNavigationContainer.mm
  • RNSModalScreen.mm
  • RNSFullWindowOverlay.mm
  • RNSScreenFooter.mm
  • RNSSafeAreaViewComponentView.mm
  • RNSSearchBar.mm
  • RNSScreenContentWrapper.mm
  • RNSScreenStackHeaderConfig.mm
  • RNSScreenStackHeaderSubview.mm

New guarded +load added (9 files):

  • RNSScrollViewMarkerComponentView.mm
  • RNSSplitHostComponentView.mm
  • RNSSplitScreenComponentView.mm
  • RNSStackHostComponentView.mm
  • RNSStackScreenComponentView.mm
  • RNSTabsHostComponentView.mm
  • RNSTabsScreenComponentView.mm
  • RNSTabsBottomAccessoryComponentView.mm
  • RNSTabsBottomAccessoryContentComponentView.mm

Test plan

  • Build xcframework with static linking (no USE_FRAMEWORKS=dynamic)
  • Verify ComponentView +load methods are not in the binary (nm check)
  • Run on x86_64 simulator alongside Akamai BMP — no crash at launch
  • Run on arm64 simulator — screens navigation works normally

Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@kkafar kkafar force-pushed the fix/guard-load-with-dynamic-frameworks branch from 9a567ec to 46fd483 Compare April 7, 2026 13:26
@kkafar
Copy link
Copy Markdown
Member

kkafar commented Apr 7, 2026

I've failed to confirm that this works, because after usage of USE_FRAMEWORKS=dynamic RNWorklets lib fails to build for some reason...

Will come back to this in few.

@kkafar
Copy link
Copy Markdown
Member

kkafar commented Apr 7, 2026

Contacted RNWorklets team and waiting for response. Will come back here once I get it and have time to look at this.

@kkafar kkafar self-assigned this Apr 15, 2026
DavidDuarte22 and others added 2 commits April 15, 2026 11:36
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.
@kkafar kkafar force-pushed the fix/guard-load-with-dynamic-frameworks branch from da35f5e to 4d7d84c Compare April 15, 2026 09:40
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.
Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I still have to check the runtime.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_FRAMEWORKS across multiple iOS ComponentView implementations.
  • Moves previously-unconditional +load methods into a dedicated “Dynamic frameworks support” section near the end of each implementation.
  • Minor method reordering in some files to keep non-+load class 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.

Comment thread ios/RNSSearchBar.mm
Copy link
Copy Markdown
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked the runtime in FabricExample. Seems to work fine ✅

Thanks for the PR!

@kkafar kkafar merged commit d4f3d71 into software-mansion:main Apr 15, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants