Skip to content

Commit 433e79d

Browse files
hryhoriiK97meta-codesync[bot]
authored andcommitted
fix(ios): replace crash-causing RCTAssert with RCTLogWarn in touch handler (#57696)
Summary: On iOS 17+, UITextView's text selection gesture recognizer can deliver `touchesMoved:`/`touchesEnded:` to `RCTSurfaceTouchHandler` without a prior `touchesBegan:` for the same touch. This happens because UIKit's internal selection gesture claims the touch begin exclusively and only forwards subsequent phases to sibling gesture recognizers. When this occurs, `_activeTouches.find(touch)` returns `end()`, and the `RCTAssert` fires, throwing an `NSException` that crashes the app in debug builds. The existing `if (iterator == end) { continue; }` guard already handles this case gracefully (and is the only code path exercised in release builds, where `RCTAssert` is a no-op). This PR downgrades the assertion to `RCTLogWarn`, preserving the diagnostic signal while eliminating the debug-only crash. This issue was discovered while investigating text selection crashes in [react-native-enriched-markdown](https://github.com/nicolo-ribaudo/react-native-enriched-markdown), where a custom `UITextView`-based Fabric component with rich text formatting (headings, paragraphs) consistently triggers the assertion during normal selection gestures. ## Changelog: [iOS] [Fixed] - Fix debug-only crash in RCTSurfaceTouchHandler from UITextView text-selection gestures on iOS 17+ Pull Request resolved: #57696 Test Plan: 1. Create a React Native app with a multiline `<TextInput>` or a custom `UITextView`-based Fabric component 2. On iOS 17+ simulator or device, in a **debug** build: - Tap to place the cursor in a text block - Attempt to select text by long-pressing and dragging to a different paragraph 3. **Before this fix**: App crashes with `NSException: "Inconsistency between local and UIKit touch registries"` 4. **After this fix**: Selection works normally. A warning is logged to the console: `"Inconsistency between local and UIKit touch registries"` 5. Verified that release builds are unaffected (RCTAssert was already a no-op in release) Reviewed By: javache Differential Revision: D113753196 Pulled By: fabriziocucci fbshipit-source-id: d4cb867818f88c4f111628d115c6be98b257f09c
1 parent 3e24033 commit 433e79d

1 file changed

Lines changed: 4 additions & 3 deletions

File tree

packages/react-native/React/Fabric/RCTSurfaceTouchHandler.mm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#import "RCTSurfaceTouchHandler.h"
99

1010
#import <React/RCTIdentifierPool.h>
11+
#import <React/RCTLog.h>
1112
#import <React/RCTUtils.h>
1213
#import <React/RCTViewComponentView.h>
1314

@@ -206,8 +207,8 @@ - (void)_updateTouches:(NSSet<UITouch *> *)touches
206207
{
207208
for (UITouch *touch in touches) {
208209
auto iterator = _activeTouches.find(touch);
209-
RCTAssert(iterator != _activeTouches.end(), @"Inconsistency between local and UIKit touch registries");
210210
if (iterator == _activeTouches.end()) {
211+
RCTLogWarn(@"Inconsistency between local and UIKit touch registries");
211212
continue;
212213
}
213214

@@ -219,8 +220,8 @@ - (void)_unregisterTouches:(NSSet<UITouch *> *)touches
219220
{
220221
for (UITouch *touch in touches) {
221222
auto iterator = _activeTouches.find(touch);
222-
RCTAssert(iterator != _activeTouches.end(), @"Inconsistency between local and UIKit touch registries");
223223
if (iterator == _activeTouches.end()) {
224+
RCTLogWarn(@"Inconsistency between local and UIKit touch registries");
224225
continue;
225226
}
226227
auto &activeTouch = iterator->second;
@@ -236,8 +237,8 @@ - (void)_unregisterTouches:(NSSet<UITouch *> *)touches
236237

237238
for (UITouch *touch in touches) {
238239
auto iterator = _activeTouches.find(touch);
239-
RCTAssert(iterator != _activeTouches.end(), @"Inconsistency between local and UIKit touch registries");
240240
if (iterator == _activeTouches.end()) {
241+
RCTLogWarn(@"Inconsistency between local and UIKit touch registries");
241242
continue;
242243
}
243244
activeTouches.push_back(iterator->second);

0 commit comments

Comments
 (0)