react-native-gesture-handler 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,6 +16,7 @@
16
16
 
17
17
  #ifdef RCT_NEW_ARCH_ENABLED
18
18
  #import <React/RCTSurfaceTouchHandler.h>
19
+ #import <React/RCTSurfaceView.h>
19
20
  #import <React/RCTViewComponentView.h>
20
21
  #else
21
22
  #import <React/RCTTouchHandler.h>
@@ -37,6 +38,8 @@
37
38
  RCTDefaultLogFunction( \
38
39
  RCTLogLevelInfo, RCTLogSourceNative, @(__FILE__), @(__LINE__), [NSString stringWithFormat:__VA_ARGS__])
39
40
 
41
+ constexpr int NEW_ARCH_NUMBER_OF_ATTACH_RETRIES = 25;
42
+
40
43
  @interface RNGestureHandlerManager () <RNGestureHandlerEventEmitter, RNRootViewGestureRecognizerDelegate>
41
44
 
42
45
  @end
@@ -45,6 +48,7 @@
45
48
  RNGestureHandlerRegistry *_registry;
46
49
  RCTUIManager *_uiManager;
47
50
  NSHashTable<RNRootViewGestureRecognizer *> *_rootViewGestureRecognizers;
51
+ NSMutableDictionary<NSNumber *, NSNumber *> *_attachRetryCounter;
48
52
  RCTEventDispatcher *_eventDispatcher;
49
53
  id _reanimatedModule;
50
54
  }
@@ -56,6 +60,7 @@
56
60
  _eventDispatcher = eventDispatcher;
57
61
  _registry = [RNGestureHandlerRegistry new];
58
62
  _rootViewGestureRecognizers = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
63
+ _attachRetryCounter = [[NSMutableDictionary alloc] init];
59
64
  _reanimatedModule = nil;
60
65
  }
61
66
  return self;
@@ -100,12 +105,39 @@
100
105
  UIView *view = [_uiManager viewForReactTag:viewTag];
101
106
 
102
107
  #ifdef RCT_NEW_ARCH_ENABLED
103
- if (view == nil) {
104
- // Happens when the view with given tag has been flattened.
105
- // We cannot attach gesture handler to a non-existent view.
108
+ if (view == nil || view.superview == nil) {
109
+ // There are a few reasons we could end up here:
110
+ // - the native view corresponding to the viewtag hasn't yet been created
111
+ // - the native view has been created, but it's not attached to window
112
+ // - the native view will not exist because it got flattened
113
+ // In the first two cases we just want to wait until the view gets created or gets attached to its superview
114
+ // In the third case we don't want to do anything but we cannot easily distinguish it here, hece the abomination
115
+ // below
116
+ // TODO: would be great to have a better solution, although it might require migration to the shadow nodes from
117
+ // viewTags
118
+
119
+ NSNumber *counter = [_attachRetryCounter objectForKey:viewTag];
120
+ if (counter == nil) {
121
+ counter = @1;
122
+ } else {
123
+ counter = [NSNumber numberWithInt:counter.intValue + 1];
124
+ }
125
+
126
+ if (counter.intValue > NEW_ARCH_NUMBER_OF_ATTACH_RETRIES) {
127
+ [_attachRetryCounter removeObjectForKey:viewTag];
128
+ } else {
129
+ [_attachRetryCounter setObject:counter forKey:viewTag];
130
+
131
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
132
+ [self attachGestureHandler:handlerTag toViewWithTag:viewTag withActionType:actionType];
133
+ });
134
+ }
135
+
106
136
  return;
107
137
  }
108
138
 
139
+ [_attachRetryCounter removeObjectForKey:viewTag];
140
+
109
141
  // I think it should be moved to RNNativeViewHandler, but that would require
110
142
  // additional logic for setting contentView.reactTag, this works for now
111
143
  if ([view isKindOfClass:[RCTViewComponentView class]]) {
@@ -164,18 +196,26 @@
164
196
 
165
197
  - (void)registerViewWithGestureRecognizerAttachedIfNeeded:(UIView *)childView
166
198
  {
199
+ #ifdef RCT_NEW_ARCH_ENABLED
200
+ UIView *touchHandlerView = childView;
201
+
202
+ while (touchHandlerView != nil && ![touchHandlerView isKindOfClass:[RCTSurfaceView class]]) {
203
+ touchHandlerView = touchHandlerView.superview;
204
+ }
205
+ #else
167
206
  UIView *parent = childView;
168
207
  while (parent != nil && ![parent respondsToSelector:@selector(touchHandler)])
169
208
  parent = parent.superview;
170
209
 
171
- // Many views can return the same touchHandler so we check if the one we want to register
172
- // is not already present in the set.
173
210
  UIView *touchHandlerView = [[parent performSelector:@selector(touchHandler)] view];
211
+ #endif // RCT_NEW_ARCH_ENABLED
174
212
 
175
213
  if (touchHandlerView == nil) {
176
214
  return;
177
215
  }
178
216
 
217
+ // Many views can return the same touchHandler so we check if the one we want to register
218
+ // is not already present in the set.
179
219
  for (UIGestureRecognizer *recognizer in touchHandlerView.gestureRecognizers) {
180
220
  if ([recognizer isKindOfClass:[RNRootViewGestureRecognizer class]]) {
181
221
  return;
@@ -208,10 +248,19 @@
208
248
  return;
209
249
 
210
250
  #ifdef RCT_NEW_ARCH_ENABLED
211
- RCTSurfaceTouchHandler *touchHandler = [viewWithTouchHandler performSelector:@selector(touchHandler)];
251
+ UIGestureRecognizer *touchHandler = nil;
252
+
253
+ // touchHandler (RCTSurfaceTouchHandler) is private in RCTFabricSurface so we have to do
254
+ // this little trick to get access to it
255
+ for (UIGestureRecognizer *recognizer in [viewWithTouchHandler gestureRecognizers]) {
256
+ if ([recognizer isKindOfClass:[RCTSurfaceTouchHandler class]]) {
257
+ touchHandler = recognizer;
258
+ break;
259
+ }
260
+ }
212
261
  #else
213
262
  RCTTouchHandler *touchHandler = [viewWithTouchHandler performSelector:@selector(touchHandler)];
214
- #endif
263
+ #endif // RCT_NEW_ARCH_ENABLED
215
264
  [touchHandler setEnabled:NO];
216
265
  [touchHandler setEnabled:YES];
217
266
  }
@@ -184,6 +184,9 @@ RCT_EXPORT_METHOD(handleClearJSResponder)
184
184
 
185
185
  RCT_EXPORT_METHOD(flushOperations)
186
186
  {
187
+ // On the new arch we rely on `flushOperations` for scheduling the operations on the UI thread.
188
+ // On the old arch we rely on `uiManagerWillPerformMounting`
189
+ #ifdef RCT_NEW_ARCH_ENABLED
187
190
  if (_operations.count == 0) {
188
191
  return;
189
192
  }
@@ -197,6 +200,7 @@ RCT_EXPORT_METHOD(flushOperations)
197
200
  operation(self->_manager);
198
201
  }
199
202
  }];
203
+ #endif // RCT_NEW_ARCH_ENABLED
200
204
  }
201
205
 
202
206
  - (void)setGestureState:(int)state forHandler:(int)handlerTag
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gesture-handler",
3
- "version": "2.10.0",
3
+ "version": "2.10.1",
4
4
  "description": "Experimental implementation of a new declarative API for gesture handling in react-native",
5
5
  "scripts": {
6
6
  "prepare": "bob build && husky install",