From a9bc3853f0cf2bb32999335c0aaf90194ea9084d Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Sun, 27 Dec 2020 03:22:59 -0800 Subject: [PATCH] Cancel touches if surface touch handler can be prevented | second try Summary: Changelog: [internal] Previous implementation, (D25684453 (https://github.com/facebook/react-native/commit/eba31d285847ef70cf22ce83fe013efa95416e3c)) which was backed out, had a bug that caused assert to fail. It was restarting internal state `RCTSurfaceTouchHandler` and lead to inconsistency. This is because touch event is a state machine and before "moved" is called, touch event had to "began". With internal state being restarted, that wasn't the case. In the previous implementation the internal state was incorrectly restarted because I thought touches would not longer receive touch events after declaring that UIGestureRecogniser shouldn't be recognised simultaneously. In this diff I take a different approach. Instead of restarting the internal state, the recogniser is first disabled and then enabled again. This cancels any ongoing touches instead of manual cleanup. ### Other approaches In the UIViewController, we could listen to `viewWillDisappear` message and cancel any ongoing touches on the surface. This would work as well (it would prevent Pressable components from being highlighted during interactive view controller dismissal) however we would need to expose existence of `RCTTouchHandler` to the view controller. This approach is also discouraged in D15734129 (https://github.com/facebook/react-native/commit/36307d87e1974aff1abac598da2fd11c4e8e23c1). Reviewed By: shergin Differential Revision: D25685536 fbshipit-source-id: ad226c82e73f841c1ebd9b92738847cc5cdc21d1 --- React/Fabric/RCTSurfaceTouchHandler.mm | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index e556a3af6d1..eb5d126eda3 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -410,4 +410,22 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act return [self canBePreventedByGestureRecognizer:otherGestureRecognizer]; } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer + shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer +{ + BOOL canBePrevented = [self canBePreventedByGestureRecognizer:otherGestureRecognizer]; + if (canBePrevented) { + [self _cancelTouches]; + } + return NO; +} + +#pragma mark - + +- (void)_cancelTouches +{ + [self setEnabled:NO]; + [self setEnabled:YES]; +} + @end