react / react/react-native

iOS: selectable Text edit menu flickers on long-press release (handleLongPress ignores gesture.state)

未关闭 适合新手
#58,079 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Needs: Author Feedback Needs: Repro Stale
主要语言
C++
星标
127k
派生
25.3k
平均合并
1 天 23 小时
30 天内合并 PR
4

描述

Description

On iOS 16+ (New Architecture), long-pressing a <Text selectable> shows the edit menu ("Copy"), and the moment the finger is lifted the menu animates out and immediately back in. It is a ~100 ms blink on every release, on every selectable Text.

Cause: RCTParagraphComponentView.handleLongPress: does not check gesture.state. A UILongPressGestureRecognizer fires its action on Began and again on Ended (and on Changed when the finger moves). The second call re-runs [_editMenuInteraction presentEditMenuWithConfiguration:], and UIKit dismisses the presented menu before presenting the new one.

https://github.com/react/react-native/blob/v0.87.0/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm#L346-L353

- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
{
  if (@available(iOS 16.0, macCatalyst 16.0, *)) {
    CGPoint location = [gesture locationInView:self];
    UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location];
    if (_editMenuInteraction) {
      [_editMenuInteraction presentEditMenuWithConfiguration:config];
    }
  } else {
    // the legacy branch is guarded by `menuController.isMenuVisible`; the iOS 16 branch is not

Fix (verified, see below):

- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
{
  if (gesture.state != UIGestureRecognizerStateBegan) {
    return;
  }
  ...

Happy to open a PR if that helps.

Steps to reproduce
  1. Render <Text selectable>Some text</Text> in any screen (New Architecture, iOS 16+).
  2. Long-press the text until "Copy" appears.
  3. Lift the finger.

Expected: the menu stays. Actual: the menu disappears and reappears at touch-up.

Evidence: screen recording of the simulator at 20 fps, OCR of each frame for "Copy" (C = menu visible, . = not):

before: ....CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC..CCCCCCCCCCCCCCCCCCCCCCC....
after:  ....CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC....

The gap in the first line is the release (Maestro longPressOn, ~3 s hold). The second line is the same scenario with the one-line guard compiled in (built from source, ios.buildReactNativeFromSource in Expo).

React Native Version

0.86.2 (code unchanged in 0.87.0)

Affected Platforms

Runtime - iOS

Output of npx @react-native-community/cli info
System: macOS 26.2
Xcode: 26.4
iOS Simulator: iPhone 17 Pro
react-native: 0.86.2 (Expo SDK 57), New Architecture, Hermes
Stacktrace or Logs
n/a (visual)
MANDATORY Reproducer

Any <Text selectable> on iOS 16+ with the New Architecture reproduces it; the bug is fully explained by the source above (the action handler is invoked for every gesture state).

Screenshots and Videos

Frame-by-frame OCR trace above.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

打开 packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm 并检查 handleLongPress:。在使用 New Architecture 的 iOS 16+ 上复现可选择 Text 的长按操作,然后验证松开后编辑菜单仍保持可见且不会闪烁。

由索引模型根据 Issue 内容生成。

评估

技术栈
ios, objective-c, react-native
领域
mobile
Issue 类型
缺陷
难度
1/5
预计耗时
1 小时以内
活跃度
活跃
描述清晰度
描述清楚
新手友好度
88/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。