Skip to content

Commit 14b690e

Browse files
authored
[iOS] Fix onFinalize callbacks on iOS 26 (#3855)
## Description This PR aims to fix callback differences between `iOS` 26 and 18. Most of them were already resolved, but there were some issues with `Pan` and `onFinalize` callback. Calling `reset` has been removed from `Tap` as it is called automatically by recognizer and leaving it resulted in double callbacks. > [!NOTE] > For related changes, see #3740, #3756 and #3849. ## Test plan <details> <summary>Tested on the following code:</summary> ```tsx import { StyleSheet, View, Text } from 'react-native'; import { GestureHandlerRootView, Gesture, GestureDetector, GestureType, } from 'react-native-gesture-handler'; function TestBox({ gestureType, bgColor, }: { gestureType: GestureType; bgColor: string; }) { const handlerName = gestureType.handlerName; const gesture = gestureType .onBegin(() => { console.log(`[${handlerName}] onBegin`); }) .onEnd((_e, s) => { console.log(`[${handlerName}] onEnd (${s})`); }) .onFinalize((_e, s) => { console.log(`[${handlerName}] onFinalize (${s})`); }) .runOnJS(true); try { // @ts-ignore this is exactly why we have the try-catch block gesture.onUpdate(() => { console.log(`[${handlerName}] onUpdate`); }); } catch { /* empty */ } return ( <View style={styles.center}> <Text>{handlerName}</Text> <GestureDetector gesture={gesture}> <View style={[styles.box, { backgroundColor: bgColor }]} /> </GestureDetector> </View> ); } export default function App() { return ( <GestureHandlerRootView style={[{ flex: 1, padding: 50 }, styles.center]}> <TestBox gestureType={Gesture.Pan()} bgColor="#b58df1" /> <TestBox gestureType={Gesture.LongPress()} bgColor="#f1a85d" /> <TestBox gestureType={Gesture.Fling()} bgColor="#5df1a8" /> <TestBox gestureType={Gesture.Tap()} bgColor="#5d8ef1" /> </GestureHandlerRootView> ); } const styles = StyleSheet.create({ center: { display: 'flex', justifyContent: 'space-around', alignItems: 'center', }, box: { height: 100, width: 100, backgroundColor: '#b58df1', borderRadius: 20, marginBottom: 30, }, }); ``` </details>
1 parent 924e38f commit 14b690e

File tree

15 files changed

+82
-67
lines changed

15 files changed

+82
-67
lines changed

apps/macos-example/macos/Podfile.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ PODS:
15051505
- ReactCommon/turbomodule/bridging
15061506
- ReactCommon/turbomodule/core
15071507
- Yoga
1508-
- RNReanimated (3.19.3):
1508+
- RNReanimated (3.19.4):
15091509
- DoubleConversion
15101510
- glog
15111511
- RCT-Folly (= 2024.11.18.00)
@@ -1525,10 +1525,10 @@ PODS:
15251525
- ReactCodegen
15261526
- ReactCommon/turbomodule/bridging
15271527
- ReactCommon/turbomodule/core
1528-
- RNReanimated/reanimated (= 3.19.3)
1529-
- RNReanimated/worklets (= 3.19.3)
1528+
- RNReanimated/reanimated (= 3.19.4)
1529+
- RNReanimated/worklets (= 3.19.4)
15301530
- Yoga
1531-
- RNReanimated/reanimated (3.19.3):
1531+
- RNReanimated/reanimated (3.19.4):
15321532
- DoubleConversion
15331533
- glog
15341534
- RCT-Folly (= 2024.11.18.00)
@@ -1548,9 +1548,9 @@ PODS:
15481548
- ReactCodegen
15491549
- ReactCommon/turbomodule/bridging
15501550
- ReactCommon/turbomodule/core
1551-
- RNReanimated/reanimated/apple (= 3.19.3)
1551+
- RNReanimated/reanimated/apple (= 3.19.4)
15521552
- Yoga
1553-
- RNReanimated/reanimated/apple (3.19.3):
1553+
- RNReanimated/reanimated/apple (3.19.4):
15541554
- DoubleConversion
15551555
- glog
15561556
- RCT-Folly (= 2024.11.18.00)
@@ -1571,7 +1571,7 @@ PODS:
15711571
- ReactCommon/turbomodule/bridging
15721572
- ReactCommon/turbomodule/core
15731573
- Yoga
1574-
- RNReanimated/worklets (3.19.3):
1574+
- RNReanimated/worklets (3.19.4):
15751575
- DoubleConversion
15761576
- glog
15771577
- RCT-Folly (= 2024.11.18.00)
@@ -1591,9 +1591,9 @@ PODS:
15911591
- ReactCodegen
15921592
- ReactCommon/turbomodule/bridging
15931593
- ReactCommon/turbomodule/core
1594-
- RNReanimated/worklets/apple (= 3.19.3)
1594+
- RNReanimated/worklets/apple (= 3.19.4)
15951595
- Yoga
1596-
- RNReanimated/worklets/apple (3.19.3):
1596+
- RNReanimated/worklets/apple (3.19.4):
15971597
- DoubleConversion
15981598
- glog
15991599
- RCT-Folly (= 2024.11.18.00)
@@ -1902,7 +1902,7 @@ SPEC CHECKSUMS:
19021902
ReactCommon: d8a297276a8a494803194d834d5ee331c6be176c
19031903
RNCAsyncStorage: b9f5f78da5d16a853fe3dc22e8268d932fc45a83
19041904
RNGestureHandler: ad19b514902de0d788e868c45ae63ea69b300433
1905-
RNReanimated: 733472f5a721122923300dadedaf2845f8739408
1905+
RNReanimated: fbef88e66ee113f1f6cb466617a9982985fa4ac6
19061906
RNSVG: 4c63b12b7b5761063bca4f20dd228f6a8370f614
19071907
SocketRocket: 03f7111df1a343b162bf5b06ead333be808e1e0a
19081908
Yoga: 68988998b6d10a0802dd7d5c6d40bf018e09ffd9

packages/react-native-gesture-handler/apple/Handlers/RNFlingHandler.m

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ @implementation RNBetterSwipeGestureRecognizer {
1616

1717
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
1818
{
19-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
19+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
2020
_gestureHandler = gestureHandler;
2121
_lastPoint = CGPointZero;
2222
_hasBegan = NO;
@@ -53,29 +53,29 @@ - (void)touchesEnded:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
5353
_lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
5454
[super touchesEnded:touches withEvent:event];
5555
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
56-
57-
[self triggerAction];
5856
}
5957

6058
- (void)touchesCancelled:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
6159
{
6260
_lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
6361
[super touchesCancelled:touches withEvent:event];
6462
[_gestureHandler.pointerTracker touchesCancelled:touches withEvent:event];
65-
66-
[self triggerAction];
6763
}
6864

6965
- (void)triggerAction
7066
{
71-
[_gestureHandler handleGesture:self];
67+
[_gestureHandler handleGesture:self fromReset:NO];
68+
}
69+
70+
- (void)triggerActionFromReset
71+
{
72+
[_gestureHandler handleGesture:self fromReset:YES];
7273
}
7374

7475
- (void)reset
7576
{
76-
// TODO: On iOS 26 swiping in "wrong" direction doesn't send `onFinalize` callback. This is because now in `reset`
77-
// default state is `UIGestureRecognizerStatePossible`
78-
[self triggerAction]; // Keeping it will not break old iOS because we check if we do not send the same state twice.
77+
[self triggerActionFromReset]; // Keeping it will not break old iOS because we check if we do not send the same state
78+
// twice.
7979
[_gestureHandler.pointerTracker reset];
8080
_hasBegan = NO;
8181
[super reset];
@@ -119,7 +119,7 @@ @implementation RNBetterSwipeGestureRecognizer {
119119

120120
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
121121
{
122-
if ((self = [super initWithTarget:self action:@selector(handleGesture:)])) {
122+
if ((self = [super initWithTarget:self action:@selector(handleGesture:fromReset:)])) {
123123
_gestureHandler = gestureHandler;
124124

125125
maxDuration = 1.0;
@@ -132,9 +132,9 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
132132
return self;
133133
}
134134

135-
- (void)handleGesture:(NSPanGestureRecognizer *)gestureRecognizer
135+
- (void)handleGesture:(NSPanGestureRecognizer *)gestureRecognizer fromReset:(BOOL)fromReset
136136
{
137-
[_gestureHandler handleGesture:self];
137+
[_gestureHandler handleGesture:self fromReset:fromReset];
138138
}
139139

140140
- (void)mouseDown:(NSEvent *)event

packages/react-native-gesture-handler/apple/Handlers/RNForceTouchHandler.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ @implementation RNForceTouchGestureRecognizer {
2828

2929
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
3030
{
31-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
31+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
3232
_gestureHandler = gestureHandler;
3333
_force = defaultForce;
3434
_minForce = defaultMinForce;

packages/react-native-gesture-handler/apple/Handlers/RNHoverHandler.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ @implementation RNBetterHoverGestureRecognizer {
4040

4141
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
4242
{
43-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
43+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
4444
_gestureHandler = gestureHandler;
4545
_hoverEffect = RNGestureHandlerHoverEffectNone;
4646
}
@@ -49,7 +49,7 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
4949

5050
- (void)triggerAction
5151
{
52-
[_gestureHandler handleGesture:self];
52+
[_gestureHandler handleGesture:self fromReset:NO];
5353
}
5454

5555
- (void)cancel

packages/react-native-gesture-handler/apple/Handlers/RNLongPressHandler.m

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler;
3333
- (NSUInteger)getDuration;
3434

3535
#if !TARGET_OS_OSX
36-
- (void)handleGesture:(UIGestureRecognizer *)recognizer;
36+
- (void)handleGesture:(UIGestureRecognizer *)recognizer fromReset:(BOOL)fromReset;
3737
#else
38-
- (void)handleGesture:(NSGestureRecognizer *)recognizer;
38+
- (void)handleGesture:(NSGestureRecognizer *)recognizer fromReset:(BOOL)fromReset;
3939
#endif
4040

4141
@end
@@ -47,21 +47,26 @@ @implementation RNBetterLongPressGestureRecognizer {
4747

4848
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
4949
{
50-
if ((self = [super initWithTarget:self action:@selector(handleGesture:)])) {
50+
if ((self = [super initWithTarget:self action:@selector(handleGesture:fromReset:)])) {
5151
_gestureHandler = gestureHandler;
5252
}
5353
return self;
5454
}
5555

56-
- (void)handleGesture:(UIGestureRecognizer *)recognizer
56+
- (void)handleGesture:(UIGestureRecognizer *)recognizer fromReset:(BOOL)fromReset
5757
{
5858
previousTime = CACurrentMediaTime();
59-
[_gestureHandler handleGesture:recognizer];
59+
[_gestureHandler handleGesture:recognizer fromReset:fromReset];
6060
}
6161

6262
- (void)triggerAction
6363
{
64-
[self handleGesture:self];
64+
[self handleGesture:self fromReset:NO];
65+
}
66+
67+
- (void)triggerActionFromReset
68+
{
69+
[self handleGesture:self fromReset:YES];
6570
}
6671

6772
- (CGPoint)translationInView
@@ -95,25 +100,19 @@ - (void)touchesMoved:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
95100
self.state = UIGestureRecognizerStateFailed;
96101
self.enabled = NO;
97102
self.enabled = YES;
98-
99-
[self triggerAction];
100103
}
101104
}
102105

103106
- (void)touchesEnded:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
104107
{
105108
[super touchesEnded:touches withEvent:event];
106109
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
107-
108-
[self triggerAction];
109110
}
110111

111112
- (void)touchesCancelled:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
112113
{
113114
[super touchesCancelled:touches withEvent:event];
114115
[_gestureHandler.pointerTracker touchesCancelled:touches withEvent:event];
115-
116-
[self triggerAction];
117116
}
118117

119118
#else
@@ -187,6 +186,7 @@ - (BOOL)shouldCancelGesture
187186

188187
- (void)reset
189188
{
189+
[self triggerActionFromReset];
190190
[_gestureHandler.pointerTracker reset];
191191

192192
[super reset];

packages/react-native-gesture-handler/apple/Handlers/RNManualHandler.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ @implementation RNManualRecognizer {
1616

1717
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
1818
{
19-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
19+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
2020
_gestureHandler = gestureHandler;
2121
_shouldSendBeginEvent = YES;
2222
}
@@ -29,7 +29,7 @@ - (void)interactionsBegan:(NSSet *)touches withEvent:(UIEvent *)event
2929
[_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
3030

3131
if (_shouldSendBeginEvent) {
32-
[_gestureHandler handleGesture:self];
32+
[_gestureHandler handleGesture:self fromReset:NO];
3333
#if TARGET_OS_OSX
3434
self.state = NSGestureRecognizerStateBegan;
3535
#endif
@@ -40,7 +40,7 @@ - (void)interactionsBegan:(NSSet *)touches withEvent:(UIEvent *)event
4040
- (void)interactionsMoved:(NSSet *)touches withEvent:(UIEvent *)event
4141
{
4242
[_gestureHandler.pointerTracker touchesMoved:touches withEvent:event];
43-
[_gestureHandler handleGesture:self];
43+
[_gestureHandler handleGesture:self fromReset:NO];
4444

4545
if ([self shouldFail]) {
4646
self.state = (self.state == UIGestureRecognizerStatePossible) ? UIGestureRecognizerStateFailed
@@ -53,7 +53,7 @@ - (void)interactionsMoved:(NSSet *)touches withEvent:(UIEvent *)event
5353
- (void)interactionsEnded:(NSSet *)touches withEvent:(UIEvent *)event
5454
{
5555
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];
56-
[_gestureHandler handleGesture:self];
56+
[_gestureHandler handleGesture:self fromReset:NO];
5757
}
5858

5959
#if !TARGET_OS_OSX

packages/react-native-gesture-handler/apple/Handlers/RNNativeViewHandler.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ @implementation RNDummyGestureRecognizer {
2929

3030
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
3131
{
32-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
32+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
3333
_gestureHandler = gestureHandler;
3434
}
3535
return self;

packages/react-native-gesture-handler/apple/Handlers/RNPanHandler.m

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ @implementation RNBetterPanGestureRecognizer {
5050

5151
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
5252
{
53-
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:)])) {
53+
if ((self = [super initWithTarget:gestureHandler action:@selector(handleGesture:fromReset:)])) {
5454
_gestureHandler = gestureHandler;
5555
_minDistSq = NAN;
5656
_minVelocityX = NAN;
@@ -75,7 +75,12 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
7575

7676
- (void)triggerAction
7777
{
78-
[_gestureHandler handleGesture:self];
78+
[_gestureHandler handleGesture:self fromReset:NO];
79+
}
80+
81+
- (void)triggerActionFromReset
82+
{
83+
[_gestureHandler handleGesture:self fromReset:YES];
7984
}
8085

8186
#if !TARGET_OS_OSX
@@ -166,7 +171,6 @@ - (void)interactionsMoved:(NSSet *)touches withEvent:(UIEvent *)event
166171
self.state = (self.state == UIGestureRecognizerStatePossible) ? UIGestureRecognizerStateFailed
167172
: UIGestureRecognizerStateCancelled;
168173

169-
[self triggerAction];
170174
[self reset];
171175
return;
172176
}
@@ -193,7 +197,6 @@ - (void)interactionsEnded:(NSSet *)touches withEvent:(UIEvent *)event
193197
#if !TARGET_OS_TV && !TARGET_OS_OSX
194198
[self tryUpdateStylusData:event];
195199
#endif
196-
[self triggerAction];
197200
}
198201

199202
- (void)interactionsCancelled:(NSSet *)touches withEvent:(UIEvent *)event
@@ -202,7 +205,6 @@ - (void)interactionsCancelled:(NSSet *)touches withEvent:(UIEvent *)event
202205
#if !TARGET_OS_TV && !TARGET_OS_OSX
203206
[self tryUpdateStylusData:event];
204207
#endif
205-
[self triggerAction];
206208
}
207209

208210
#if TARGET_OS_OSX
@@ -259,7 +261,7 @@ - (void)touchesCancelled:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)ev
259261

260262
- (void)reset
261263
{
262-
[self triggerAction];
264+
[self triggerActionFromReset];
263265
[_gestureHandler.pointerTracker reset];
264266
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(activateAfterLongPress) object:nil];
265267
self.enabled = YES;

packages/react-native-gesture-handler/apple/Handlers/RNPinchHandler.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ @implementation RNBetterPinchRecognizer {
3333

3434
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
3535
{
36-
if ((self = [super initWithTarget:self action:@selector(handleGesture:)])) {
36+
if ((self = [super initWithTarget:self action:@selector(handleGesture:fromReset:)])) {
3737
_gestureHandler = gestureHandler;
3838
}
3939
#if TARGET_OS_OSX
@@ -43,7 +43,7 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
4343
return self;
4444
}
4545

46-
- (void)handleGesture:(UIGestureRecognizer *)recognizer
46+
- (void)handleGesture:(UIGestureRecognizer *)recognizer fromReset:(BOOL)fromReset
4747
{
4848
if (self.state == UIGestureRecognizerStateBegan) {
4949
#if TARGET_OS_OSX
@@ -52,7 +52,7 @@ - (void)handleGesture:(UIGestureRecognizer *)recognizer
5252
self.scale = 1;
5353
#endif
5454
}
55-
[_gestureHandler handleGesture:recognizer];
55+
[_gestureHandler handleGesture:recognizer fromReset:fromReset];
5656
}
5757

5858
- (void)interactionsBegan:(NSSet *)touches withEvent:(UIEvent *)event

packages/react-native-gesture-handler/apple/Handlers/RNRotationHandler.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ @implementation RNBetterRotationRecognizer {
3131

3232
- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
3333
{
34-
if ((self = [super initWithTarget:self action:@selector(handleGesture:)])) {
34+
if ((self = [super initWithTarget:self action:@selector(handleGesture:fromReset:)])) {
3535
_gestureHandler = gestureHandler;
3636
}
3737
#if TARGET_OS_OSX
@@ -41,12 +41,12 @@ - (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler
4141
return self;
4242
}
4343

44-
- (void)handleGesture:(UIGestureRecognizer *)recognizer
44+
- (void)handleGesture:(UIGestureRecognizer *)recognizer fromReset:(BOOL)fromReset
4545
{
4646
if (self.state == UIGestureRecognizerStateBegan) {
4747
self.rotation = 0;
4848
}
49-
[_gestureHandler handleGesture:recognizer];
49+
[_gestureHandler handleGesture:recognizer fromReset:fromReset];
5050
}
5151

5252
- (void)interactionsBegan:(NSSet *)touches withEvent:(UIEvent *)event

0 commit comments

Comments
 (0)