Skip to content

Commit

Permalink
Attach to RNRootViewGestureRecognizer instead of root view (software-…
Browse files Browse the repository at this point in the history
  • Loading branch information
WoLewicki authored May 4, 2021
1 parent d913ded commit fbb956b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 36 deletions.
2 changes: 1 addition & 1 deletion ios/RNGestureHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ if (value != nil) recognizer.prop = [RCTConvert type:value]; \
@protocol RNRootViewGestureRecognizerDelegate <UIGestureRecognizerDelegate>

- (void)gestureRecognizer:(nullable UIGestureRecognizer *)gestureRecognizer
didActivateInRootView:(nullable UIView *)rootView;
didActivateInViewWithTouchHandler:(nullable UIView *)viewWithTouchHandler;

@end

Expand Down
65 changes: 31 additions & 34 deletions ios/RNGestureHandlerManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ @implementation RNGestureHandlerManager
{
RNGestureHandlerRegistry *_registry;
RCTUIManager *_uiManager;
NSHashTable<UIView *> *_rootViews;
NSHashTable<RNRootViewGestureRecognizer *> *_rootViewGestureRecognizers;
RCTEventDispatcher *_eventDispatcher;
}

Expand All @@ -51,7 +51,7 @@ - (instancetype)initWithUIManager:(RCTUIManager *)uiManager
_uiManager = uiManager;
_eventDispatcher = eventDispatcher;
_registry = [RNGestureHandlerRegistry new];
_rootViews = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
_rootViewGestureRecognizers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
}
return self;
}
Expand Down Expand Up @@ -97,8 +97,8 @@ - (void)attachGestureHandler:(nonnull NSNumber *)handlerTag

[_registry attachHandlerWithTag:handlerTag toView:view];

// register root view if not already there
[self registerRootViewIfNeeded:view];
// register view if not already there
[self registerViewWithGestureRecognizerAttachedIfNeeded:view];
}

- (void)updateGestureHandler:(NSNumber *)handlerTag config:(NSDictionary *)config
Expand All @@ -115,12 +115,8 @@ - (void)dropGestureHandler:(NSNumber *)handlerTag
- (void)handleSetJSResponder:(NSNumber *)viewTag blockNativeResponder:(NSNumber *)blockNativeResponder
{
if ([blockNativeResponder boolValue]) {
for (RCTRootView *rootView in _rootViews) {
for (UIGestureRecognizer *recognizer in rootView.gestureRecognizers) {
if ([recognizer isKindOfClass:[RNRootViewGestureRecognizer class]]) {
[(RNRootViewGestureRecognizer *)recognizer blockOtherRecognizers];
}
}
for (RNRootViewGestureRecognizer *recognizer in _rootViewGestureRecognizers) {
[recognizer blockOtherRecognizers];
}
}
}
Expand All @@ -132,25 +128,35 @@ - (void)handleClearJSResponder

#pragma mark Root Views Management

- (void)registerRootViewIfNeeded:(UIView*)childView
- (void)registerViewWithGestureRecognizerAttachedIfNeeded:(UIView *)childView
{
UIView *parent = childView;
while (parent != nil && ![parent isKindOfClass:[RCTRootView class]]) parent = parent.superview;

RCTRootView *rootView = (RCTRootView *)parent;
UIView *rootContentView = rootView.contentView;
if (rootContentView != nil && ![_rootViews containsObject:rootContentView]) {
RCTLifecycleLog(@"[GESTURE HANDLER] Initialize gesture handler for root view %@", rootContentView);
[_rootViews addObject:rootContentView];
RNRootViewGestureRecognizer *recognizer = [RNRootViewGestureRecognizer new];
recognizer.delegate = self;
rootContentView.userInteractionEnabled = YES;
[rootContentView addGestureRecognizer:recognizer];
while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)]) parent = parent.superview;

// Many views can return the same touchHandler so we check if the one we want to register
// is not already present in the set.
UIView *touchHandlerView = [[parent performSelector:@selector(touchHandler)] view];

if (touchHandlerView == nil) {
return;
}

for (UIGestureRecognizer *recognizer in touchHandlerView.gestureRecognizers) {
if ([recognizer isKindOfClass:[RNRootViewGestureRecognizer class]]) {
return;
}
}

RCTLifecycleLog(@"[GESTURE HANDLER] Initialize gesture handler for view %@", touchHandlerView);
RNRootViewGestureRecognizer *recognizer = [RNRootViewGestureRecognizer new];
recognizer.delegate = self;
touchHandlerView.userInteractionEnabled = YES;
[touchHandlerView addGestureRecognizer:recognizer];
[_rootViewGestureRecognizers addObject:recognizer];
}

- (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
didActivateInRootView:(UIView *)rootContentView
didActivateInViewWithTouchHandler:(UIView *)viewWithTouchHandler
{
// Cancel touches in RN's root view in order to cancel all in-js recognizers

Expand All @@ -165,17 +171,8 @@ - (void)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
// Once the upstream fix lands the line below along with this comment can be removed
if ([gestureRecognizer.view isKindOfClass:[UIScrollView class]]) return;

UIView *parent = rootContentView.superview;
if ([parent isKindOfClass:[RCTRootView class]]) {
[((RCTRootContentView*)rootContentView).touchHandler cancel];
}
}

- (void)dealloc
{
if ([_rootViews count] > 0) {
RCTLifecycleLog(@"[GESTURE HANDLER] Tearing down gesture handler registered for views %@", _rootViews);
}
RCTTouchHandler *touchHandler = [viewWithTouchHandler performSelector:@selector(touchHandler)];
[touchHandler cancel];
}

#pragma mark Events
Expand Down
2 changes: 1 addition & 1 deletion ios/RNRootViewGestureRecognizer.m
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestu
{
// When this method is called it means that one of handlers has activated, in this case we want
// to send an info to JS so that it cancells all JS responders
[self.delegate gestureRecognizer:preventingGestureRecognizer didActivateInRootView:self.view];
[self.delegate gestureRecognizer:preventingGestureRecognizer didActivateInViewWithTouchHandler:self.view];
return [super canBePreventedByGestureRecognizer:preventingGestureRecognizer];
}

Expand Down

0 comments on commit fbb956b

Please sign in to comment.