Skip to content

Commit e08a197

Browse files
okwasniewskifacebook-github-bot
authored andcommitted
feat(iOS): migrate deprecated UIMenuController to UIEditMenuInteraction (#41125)
Summary: The goal of this PR is to migrate deprecated `UIMenuController` to `UIEditMenuInteraction`. `UIMenuController` has been deprecated in iOS 16 and for that reason it's not available for VisionOS. ## Recording https://github.com/facebook/react-native/assets/52801365/fed994be-d444-462a-9ed0-39b50531425d bypass-github-export-checks ## Changelog: <!-- Help reviewers and the release process by writing your own changelog entry. Pick one each for the category and type tags: [ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> [IOS] [CHANGED] - Migrate RCTTextView to UIEditMenuInteraction Pull Request resolved: #41125 Test Plan: Launch RNTester and check for "Selectable Text" example and check that it works for iOS 16/17. Reviewed By: javache Differential Revision: D50551016 Pulled By: cipolleschi fbshipit-source-id: 558ecc5a04a5daa9c4360fabddcab28fba72a323
1 parent 7853b06 commit e08a197

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

packages/react-native/Libraries/Text/Text/RCTTextView.mm

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616

1717
#import <QuartzCore/QuartzCore.h>
1818

19+
@interface RCTTextView () <UIEditMenuInteractionDelegate>
20+
21+
@property (nonatomic, nullable) UIEditMenuInteraction *editMenuInteraction API_AVAILABLE(ios(16.0));
22+
23+
@end
24+
1925
@implementation RCTTextView {
2026
CAShapeLayer *_highlightLayer;
2127
UILongPressGestureRecognizer *_longPressGestureRecognizer;
@@ -213,19 +219,37 @@ - (void)enableContextMenu
213219
{
214220
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
215221
action:@selector(handleLongPress:)];
222+
if (@available(iOS 16.0, *)) {
223+
_editMenuInteraction = [[UIEditMenuInteraction alloc] initWithDelegate:self];
224+
[self addInteraction:_editMenuInteraction];
225+
}
226+
216227
[self addGestureRecognizer:_longPressGestureRecognizer];
217228
}
218229

219230
- (void)disableContextMenu
220231
{
221232
[self removeGestureRecognizer:_longPressGestureRecognizer];
233+
234+
if (@available(iOS 16.0, *)) {
235+
[self removeInteraction:_editMenuInteraction];
236+
_editMenuInteraction = nil;
237+
}
222238
_longPressGestureRecognizer = nil;
223239
}
224240

225241
- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
226242
{
227-
// TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
228243
#if !TARGET_OS_UIKITFORMAC
244+
if (@available(iOS 16.0, *)) {
245+
CGPoint location = [gesture locationInView:self];
246+
UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location];
247+
if (_editMenuInteraction) {
248+
[_editMenuInteraction presentEditMenuWithConfiguration:config];
249+
}
250+
return;
251+
}
252+
// TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
229253
UIMenuController *menuController = [UIMenuController sharedMenuController];
230254

231255
if (menuController.isMenuVisible) {

packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424

2525
using namespace facebook::react;
2626

27+
@interface RCTParagraphComponentView () <UIEditMenuInteractionDelegate>
28+
29+
@property (nonatomic, nullable) UIEditMenuInteraction *editMenuInteraction API_AVAILABLE(ios(16.0));
30+
31+
@end
32+
2733
@implementation RCTParagraphComponentView {
2834
ParagraphShadowNode::ConcreteState::Shared _state;
2935
ParagraphAttributes _paragraphAttributes;
@@ -211,19 +217,36 @@ - (void)enableContextMenu
211217
{
212218
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
213219
action:@selector(handleLongPress:)];
220+
221+
if (@available(iOS 16.0, *)) {
222+
_editMenuInteraction = [[UIEditMenuInteraction alloc] initWithDelegate:self];
223+
[self addInteraction:_editMenuInteraction];
224+
}
214225
[self addGestureRecognizer:_longPressGestureRecognizer];
215226
}
216227

217228
- (void)disableContextMenu
218229
{
219230
[self removeGestureRecognizer:_longPressGestureRecognizer];
231+
if (@available(iOS 16.0, *)) {
232+
[self removeInteraction:_editMenuInteraction];
233+
_editMenuInteraction = nil;
234+
}
220235
_longPressGestureRecognizer = nil;
221236
}
222237

223238
- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture
224239
{
225-
// TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
226240
#if !TARGET_OS_UIKITFORMAC
241+
if (@available(iOS 16.0, *)) {
242+
CGPoint location = [gesture locationInView:self];
243+
UIEditMenuConfiguration *config = [UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:location];
244+
if (_editMenuInteraction) {
245+
[_editMenuInteraction presentEditMenuWithConfiguration:config];
246+
}
247+
return;
248+
}
249+
// TODO: Adopt showMenuFromRect (necessary for UIKitForMac)
227250
UIMenuController *menuController = [UIMenuController sharedMenuController];
228251

229252
if (menuController.isMenuVisible) {

0 commit comments

Comments
 (0)