Skip to content

fix(iOS): forward-declare RCTSurfaceTouchHandler in UIView+RNSUtility.h#3986

Merged
kkafar merged 1 commit intosoftware-mansion:mainfrom
zhe-qi:fix/uiview-rnsutility-header-purity
May 8, 2026
Merged

fix(iOS): forward-declare RCTSurfaceTouchHandler in UIView+RNSUtility.h#3986
kkafar merged 1 commit intosoftware-mansion:mainfrom
zhe-qi:fix/uiview-rnsutility-header-purity

Conversation

@zhe-qi
Copy link
Copy Markdown
Contributor

@zhe-qi zhe-qi commented May 7, 2026

Summary

ios/utils/UIView+RNSUtility.h declares methods returning RCTSurfaceTouchHandler * and currently #imports <React/RCTSurfaceTouchHandler.h> directly in the public header. That header is shipped in the React-RCTFabric clang module, not React — so under use_frameworks!:linkage => :static + new arch, any consumer module that imports the RNScreens clang module (e.g. ExpoRouter) fails Clang's module dependency scanning before compilation:

error: Clang dependency scanning failure: While building module 'RNScreens'
  UIView+RNSUtility.h: 'React/RCTSurfaceTouchHandler.h' file not found
error: Compilation search paths unable to resolve module dependency: 'RNScreens'
(in target 'ExpoRouter' from project 'Pods')

This PR moves the import out of the public surface:

  • UIView+RNSUtility.h: replace #import <React/RCTSurfaceTouchHandler.h> with @class RCTSurfaceTouchHandler; forward declaration. Replace <Foundation/Foundation.h> with <UIKit/UIKit.h> (since the fabric header was previously providing UIKit transitively, and this is a UIView category — matching the sibling UINavigationBar+RNSUtility.h).
  • UIView+RNSUtility.mm: add the real #import <React/RCTSurfaceTouchHandler.h>.

This matches the pattern already used by RNSScreenStack.mm, where fabric-internal imports stay inside the implementation file.

Fixes #3985.

Compatibility

All current internal consumers of UIView+RNSUtility.h (RNSScreenStack.mm, RNSScreen.mm, and UIView+RNSUtility.mm itself) already #import <React/RCTSurfaceTouchHandler.h> directly, so they retain access to the type without relying on transitive imports from the public header. No call sites need updating.

The change is purely a compile-time refactor — no symbols, return types, ABI, or runtime behavior change.

Test plan

  • Verified on the consumer side: under use_frameworks!:static + new arch + RN 0.85.3, the patched header allows ExpoRouter to compile against RNScreens. Without the fix, expo run:ios fails on the Clang module dependency scanning error above.
  • Maintainers: existing CI matrix should cover both use_frameworks! and non-frameworks builds across new/legacy arch.

Related

The public header `ios/utils/UIView+RNSUtility.h` directly imports
`<React/RCTSurfaceTouchHandler.h>`, which is shipped in the
`React-RCTFabric` clang module rather than `React`. Under
`use_frameworks!:linkage => :static` + new architecture, any consumer
module that imports the `RNScreens` clang module (e.g. ExpoRouter)
inherits this transitive import without the matching framework search
path, and Clang's module dependency scanning fails before compilation:

  error: Clang dependency scanning failure: While building module
    'RNScreens' ... 'React/RCTSurfaceTouchHandler.h' file not found
  error: Compilation search paths unable to resolve module dependency:
    'RNScreens' (in target 'ExpoRouter' from project 'Pods')

Move the import out of the public surface: forward-declare
`RCTSurfaceTouchHandler` in the header and `#import` it in the .mm.
This matches the convention already used by `RNSScreenStack.mm` and
sibling utility headers (`UINavigationBar+RNSUtility.h`), and keeps
the public module interface free of fabric-internal dependencies.

All existing internal consumers (`RNSScreenStack.mm`, `RNSScreen.mm`,
`UIView+RNSUtility.mm`) already import `RCTSurfaceTouchHandler.h`
directly, so no call sites need updating.
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, thanks for the PR. Seems like something I'll land. I just have one question.


#import <Foundation/Foundation.h>
#import <React/RCTSurfaceTouchHandler.h>
#import <UIKit/UIKit.h>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why change Foundation import for UIKit import? How is it related to the issue?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's explained in #3985 ("Suggested fix" section).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks. Makes sense.

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'm good with this change. @kligarski would you mind giving a round of test (build with the configuration the OP suggests) & in case of success landing it?

@kligarski
Copy link
Copy Markdown
Contributor

I'm good with this change. @kligarski would you mind giving a round of test (build with the configuration the OP suggests) & in case of success landing it?

Okay, I'll test it on Monday.

@kligarski kligarski self-assigned this May 7, 2026
@kkafar kkafar assigned kkafar and unassigned kligarski May 8, 2026
@kkafar kkafar self-requested a review May 8, 2026 11:13
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 gave it a round of testing & seems to work fine. Thank you.

I'll cherry-pick this change to 4.25.0 release.

@kkafar kkafar merged commit f92e0d1 into software-mansion:main May 8, 2026
6 checks passed
@zhe-qi zhe-qi deleted the fix/uiview-rnsutility-header-purity branch May 9, 2026 05:35
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.

[iOS] UIView+RNSUtility.h leaks RCTSurfaceTouchHandler import, breaks Clang module dependency scanning under use_frameworks!:static

3 participants