From 36307d87e1974aff1abac598da2fd11c4e8e23c1 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Tue, 11 Jun 2019 07:25:18 -0700 Subject: [PATCH] Deprecation of `-[RCTRootView cancelTouches]` Summary: The necessity of this feature was removed in 2017. To intercept React Native gesture recognizer, implement UIGestureRecognizer delegate for conflicting gestures. Here is the quote from the internal note: > Previously we had lots of super weird bugs where React Native would inaccurately recognize touch gestures which were meant to be addressed by the native environment. Usually, these bugs occurred as unintentional taps happening right after swipe gestures. In all of these cases, we had to manually call method `cancelTouches` as part of an external gesture recognition process which prevented touch delivery to React Native. Furthermore, we had to delay touch delivery to React Native to wait for these cancellations. That code always looked like a hack (in the bad meaning of this word), like in some random place something dispatch event to another random place where something finally calls `cancelTouches`, yak. It was super annoying because it required adding this hack to all existing apps and screens, and because sometimes it was even too late to cancel touches. > We fixed that. Instead of delaying touch delivery and waiting for calls to `cancelTouches`, we set up the React Native gesture recognizer in such way that it always agrees to fail in favor of any native gestures (from non-RN-based and served views which are placed higher in a hierarchy). React Native will now cancel all active touches itself so that we no longer need to call `cancelTouches` manually. We already removed all these calls and supported code from Facebook and Instagram. See also: https://github.com/facebook/react-native/pull/25193 Reviewed By: PeteTheHeat Differential Revision: D15734129 fbshipit-source-id: 289f77a437cb40199c591153b5801d24d0c10d1e --- React/Base/RCTRootView.h | 27 ++++++++------------------- React/Base/RCTRootView.m | 11 ++++++----- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/React/Base/RCTRootView.h b/React/Base/RCTRootView.h index 348d08b08f2..7ef03775aab 100644 --- a/React/Base/RCTRootView.h +++ b/React/Base/RCTRootView.h @@ -117,25 +117,6 @@ NSString *const RCTContentDidAppearNotification; */ @property (nonatomic, strong, nullable) UIView *loadingView; -/** - * Calling this will result in emitting a "touches cancelled" event to js, - * which effectively cancels all js "gesture recognizers" such as touchable components - * (unless they explicitely ignore cancellation events, but no one should do that). - * - * This API is exposed for integration purposes where you embed RN rootView - * in a native view with a native gesture recognizer, - * whose activation should prevent any in-flight js "gesture recognizer" from activating. - * - * An example would be RN rootView embedded in an UIScrollView. - * When you touch down on a touchable component and drag your finger up, - * you don't want any touch to be registered as soon as the UIScrollView starts scrolling. - * - * Note that this doesn't help with tapping on a touchable element that is being scrolled, - * unless you can call cancelTouches exactly between "touches began" and "touches ended" events. - * This is a reason why this API may be soon removed in favor of a better solution. - */ -- (void)cancelTouches; - /** * When set, any touches on the RCTRootView that are not matched up to any of the child * views will be passed to siblings of the RCTRootView. See -[UIView hitTest:withEvent:] @@ -168,6 +149,14 @@ NSString *const RCTContentDidAppearNotification; @property (readonly, nonatomic, assign) CGSize intrinsicSize __deprecated_msg("Use `intrinsicContentSize` instead."); +/** + * This methods is deprecated and will be removed soon. + * To interrupt a React Native gesture recognizer, use the standard + * `UIGestureRecognizer` negotiation process. + * See `UIGestureRecognizerDelegate` for more details. + */ +- (void)cancelTouches; + @end NS_ASSUME_NONNULL_END diff --git a/React/Base/RCTRootView.m b/React/Base/RCTRootView.m index 0f4e22bc170..f806a4974dc 100644 --- a/React/Base/RCTRootView.m +++ b/React/Base/RCTRootView.m @@ -372,11 +372,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) [_contentView invalidate]; } -- (void)cancelTouches -{ - [[_contentView touchHandler] cancel]; -} - @end @implementation RCTRootView (Deprecated) @@ -387,4 +382,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) return self.intrinsicContentSize; } +- (void)cancelTouches +{ + RCTLogWarn(@"`-[RCTRootView cancelTouches]` is deprecated and will be deleted soon."); + [[_contentView touchHandler] cancel]; +} + @end