Skip to content

Commit 2a90922

Browse files
authored
[iOS] Remove dropped native handlers (#3819)
## What is happening While working on #3800 I've noticed frequent crashes on `iOS`. I'll explain this using the demo from the test code, basically two screens, second screen has a `RectButton`. 1. Navigate to second screen 2. Go back 3. Navigate to the second screen again 4. App crashes Sometime it crashes immediately on startup. ## Why is it happening? `Native` handlers are handled differently compared to others. The main problem was that we tried to attach handler that was previously dropped, but `NativeDetector` has no information that this happened. The flow here looks as follows: 1. We navigate to screen with button 2. `addSubview` is called - at this point it won't attach anything as `_nativeHandlers` is empty 3. `updateProps` is called - handlers are attached 4. We navigate back to first screen 5. Handler is dropped 6. We navigate again to second screen 7. `addSubview` is called - it tries to attach handler that was dropped, therefore app crashes ## Solution To fix this issue, we clear `_nativeHandlers` in `prepareForRecycle` method. ## Test plan <details> <summary>I've tested it on my branch with components re-written to new API, using the following code in EmptyExample:</summary> ```tsx import React from 'react'; import { StyleSheet, View } from 'react-native'; import { RectButton } from 'react-native-gesture-handler'; export default function EmptyExample() { return ( <View style={styles.container}> <RectButton style={styles.button} onPress={() => console.log('Hello World!')} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, button: { width: 100, height: 30, borderRadius: 10, backgroundColor: 'pink', }, }); ``` </details>
1 parent 48e3a79 commit 2a90922

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

packages/react-native-gesture-handler/apple/RNGestureHandlerDetector.mm

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ + (BOOL)shouldBeRecycled
3333
- (instancetype)initWithFrame:(CGRect)frame
3434
{
3535
if (self = [super initWithFrame:frame]) {
36-
static const auto defaultProps = std::make_shared<const RNGestureHandlerDetectorProps>();
37-
_props = defaultProps;
38-
_moduleId = -1;
39-
_nativeHandlers = [NSMutableSet set];
40-
_attachedHandlers = [NSMutableSet set];
36+
[self setDefaultProps];
4137
}
4238

4339
return self;
@@ -72,6 +68,15 @@ - (void)willMoveToWindow:(RNGHWindow *)newWindow
7268
}
7369
}
7470

71+
- (void)setDefaultProps
72+
{
73+
static const auto defaultProps = std::make_shared<const RNGestureHandlerDetectorProps>();
74+
_props = defaultProps;
75+
_moduleId = -1;
76+
_nativeHandlers = [NSMutableSet set];
77+
_attachedHandlers = [NSMutableSet set];
78+
}
79+
7580
- (void)dispatchStateChangeEvent:(RNGestureHandlerDetectorEventEmitter::OnGestureHandlerStateChange)event
7681
{
7782
if (_eventEmitter != nullptr) {
@@ -127,6 +132,13 @@ - (BOOL)shouldAttachGestureToSubview:(NSNumber *)handlerTag
127132
return [[[handlerManager registry] handlerWithTag:handlerTag] wantsToAttachDirectlyToView];
128133
}
129134

135+
- (void)prepareForRecycle
136+
{
137+
[super prepareForRecycle];
138+
139+
[self setDefaultProps];
140+
}
141+
130142
- (void)didAddSubview:(RNGHUIView *)view
131143
{
132144
[super didAddSubview:view];

0 commit comments

Comments
 (0)