Skip to content

Commit c68bf94

Browse files
rileysaym-bert
authored andcommitted
[iOS] Keep button hit testing within its own subtree (#4495)
Fixes #4494. When a disabled `RNGestureHandlerButton` has no eligible touch target, the hit-test loop can continue past the button and return an ancestor outside its subtree. This change returns `nil` when the search reaches the button itself without finding an eligible target. Eligible descendants can still be selected before reaching that boundary. The guard prevents the SwiftUI-backed blur crash in my device testing. The suspected connection between returning a hosting ancestor and recursive hit testing is described in the linked issue. Tested the same boundary guard in my app’s test screen on an iPhone 16 Pro running iOS 26.5.2, using an Expo SDK 57 development build with React Native 0.86.3 and Gesture Handler 3.2.1. React Native’s experimental `enableSwiftUIBasedFilters` flag was enabled. - Original behaviour: tapping the disabled outer area crashes. - Boundary guard enabled, pointer-events workaround off: tapping the same area no longer crashes. Reproduction project and build instructions: https://github.com/rileysay/rngh-swiftui-hit-test-repro The standalone project has built successfully on EAS. The device observations above were recorded using the test screen in my original app. AI assistance: I used Codex to help investigate the native code, prepare the reproduction project, and propose this patch. I personally verified the device observations above.
1 parent d21cb85 commit c68bf94

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎packages/react-native-gesture-handler/apple/RNGestureHandlerButton.mm‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ - (RNGHUIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
118118
}
119119

120120
RNGHUIView *inner = [super hitTest:point withEvent:event];
121-
while (inner && ![self shouldHandleTouch:inner]) {
121+
while (inner && inner != self && ![self shouldHandleTouch:inner]) {
122122
inner = inner.superview;
123123
}
124124
return inner;

0 commit comments

Comments
 (0)