Make RCTEventDispatcher TurboModule-compatible

Summary:
This diff ended up being a bit more complicated than I anticipated, since the source files in `ReactInternal` were depending on `RCTEventDispatcher`. I made the following changes:
1. Make `RCTEventDispatcher` a `protocol`, keep it in `ReactInternal`.
2. Rename the `RCTEventDispatcher` NativeModule to `RCTEventDispatcherModule`, make it conform to the `RCTEventEmitter` `protocol`, and move it to `CoreModules`.
3. Where necessary, replace categories of `RCTEventDispatcher` with functions.

Changelog:
[iOS][Added] - Make RCTEventDispatcher TurboModule-comaptible

Reviewed By: fkgozali

Differential Revision: D18439488

fbshipit-source-id: b3da15c29459fddf884519f33b0c3b8c036b5539
This commit is contained in:
Lulu Wu
2020-10-14 02:40:10 -07:00
committed by Facebook GitHub Bot
parent d5076c6c8f
commit ea93151f21
46 changed files with 301 additions and 284 deletions
-1
View File
@@ -9,7 +9,6 @@
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTImageBlurUtils.h>
#import <React/RCTImageSource.h>
#import <React/RCTImageUtils.h>
@@ -9,7 +9,6 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import <React/RCTLog.h>
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import "RCTValueAnimatedNode.h"
@@ -6,7 +6,7 @@
*/
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTSurfacePresenterStub.h>
#import <React/RCTUIManager.h>
@@ -9,6 +9,7 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTUIManager.h>
#import <React/RCTSurfacePresenterStub.h>
#import <React/RCTEventDispatcherProtocol.h>
@protocol RCTValueAnimatedNodeObserver;
@@ -6,7 +6,7 @@
*/
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTSurfacePresenterStub.h>
#import <React/RCTUIManager.h>
-1
View File
@@ -11,7 +11,6 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTAssert.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTLog.h>
#import <React/RCTNetworkTask.h>
#import <React/RCTNetworking.h>
@@ -12,7 +12,6 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import "RCTPushNotificationPlugins.h"
+1 -1
View File
@@ -10,7 +10,7 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTUtils.h>
#import "RCTSettingsPlugins.h"
@@ -13,7 +13,6 @@
#import "RCTBackedTextInputViewProtocol.h"
@class RCTBridge;
@class RCTEventDispatcher;
@class RCTTextAttributes;
@class RCTTextSelection;
@@ -9,7 +9,7 @@
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTUIManager.h>
#import <React/RCTUtils.h>
#import <React/UIView+React.h>
@@ -21,7 +21,7 @@
@implementation RCTBaseTextInputView {
__weak RCTBridge *_bridge;
__weak RCTEventDispatcher *_eventDispatcher;
__weak id<RCTEventDispatcherProtocol> _eventDispatcher;
BOOL _hasInputAccesoryView;
NSString *_Nullable _predictedText;
BOOL _didMoveToWindow;
-1
View File
@@ -15,7 +15,6 @@
@class JSValue;
@class RCTBridge;
@class RCTEventDispatcher;
@class RCTPerformanceLogger;
/**
-1
View File
@@ -11,7 +11,6 @@
#import <objc/runtime.h>
#import "RCTConvert.h"
#import "RCTEventDispatcher.h"
#if RCT_ENABLE_INSPECTOR
#import "RCTInspectorDevServerHelper.h"
#endif
+1 -1
View File
@@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
NS_ASSUME_NONNULL_BEGIN
+3 -216
View File
@@ -5,14 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
#import "RCTEventDispatcher.h"
#import "RCTAssert.h"
#import "RCTBridge+Private.h"
#import "RCTBridge.h"
#import "RCTComponentEvent.h"
#import "RCTProfile.h"
#import "RCTUtils.h"
#import "RCTEventDispatcherProtocol.h"
const NSInteger RCTTextUpdateLagWarningThreshold = 3;
@@ -27,217 +20,11 @@ NSString *RCTNormalizeInputEventName(NSString *eventName)
return eventName;
}
static NSNumber *RCTGetEventID(NSNumber *viewTag, NSString *eventName, uint16_t coalescingKey)
{
return @(viewTag.intValue | (((uint64_t)eventName.hash & 0xFFFF) << 32) | (((uint64_t)coalescingKey) << 48));
}
static uint16_t RCTUniqueCoalescingKeyGenerator = 0;
@implementation RCTEventDispatcher {
// We need this lock to protect access to _events, _eventQueue and _eventsDispatchScheduled. It's filled in on main
// thread and consumed on js thread.
NSLock *_eventQueueLock;
// We have this id -> event mapping so we coalesce effectively.
NSMutableDictionary<NSNumber *, id<RCTEvent>> *_events;
// This array contains ids of events in order they come in, so we can emit them to JS in the exact same order.
NSMutableArray<NSNumber *> *_eventQueue;
BOOL _eventsDispatchScheduled;
NSHashTable<id<RCTEventDispatcherObserver>> *_observers;
NSLock *_observersLock;
}
@synthesize bridge = _bridge;
@synthesize dispatchToJSThread = _dispatchToJSThread;
@synthesize invokeJS = _invokeJS;
@synthesize invokeJSWithModuleDotMethod = _invokeJSWithModuleDotMethod;
RCT_EXPORT_MODULE()
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
_events = [NSMutableDictionary new];
_eventQueue = [NSMutableArray new];
_eventQueueLock = [NSLock new];
_eventsDispatchScheduled = NO;
_observers = [NSHashTable weakObjectsHashTable];
_observersLock = [NSLock new];
}
- (void)sendAppEventWithName:(NSString *)name body:(id)body
{
if (_bridge) {
[_bridge enqueueJSCall:@"RCTNativeAppEventEmitter"
method:@"emit"
args:body ? @[ name, body ] : @[ name ]
completion:NULL];
} else {
_invokeJS(@"RCTNativeAppEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]);
}
}
- (void)sendDeviceEventWithName:(NSString *)name body:(id)body
{
if (_bridge) {
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter"
method:@"emit"
args:body ? @[ name, body ] : @[ name ]
completion:NULL];
} else {
_invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]);
}
}
- (void)sendTextEventWithType:(RCTTextEventType)type
reactTag:(NSNumber *)reactTag
text:(NSString *)text
key:(NSString *)key
eventCount:(NSInteger)eventCount
{
static NSString *events[] = {@"focus", @"blur", @"change", @"submitEditing", @"endEditing", @"keyPress"};
NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithDictionary:@{
@"eventCount" : @(eventCount),
}];
if (text) {
body[@"text"] = text;
}
if (key) {
if (key.length == 0) {
key = @"Backspace"; // backspace
} else {
switch ([key characterAtIndex:0]) {
case '\t':
key = @"Tab";
break;
case '\n':
key = @"Enter";
default:
break;
}
}
body[@"key"] = key;
}
RCTComponentEvent *event = [[RCTComponentEvent alloc] initWithName:events[type] viewTag:reactTag body:body];
[self sendEvent:event];
}
- (void)sendEvent:(id<RCTEvent>)event
{
[_observersLock lock];
for (id<RCTEventDispatcherObserver> observer in _observers) {
[observer eventDispatcherWillDispatchEvent:event];
}
[_observersLock unlock];
[_eventQueueLock lock];
NSNumber *eventID;
if (event.canCoalesce) {
eventID = RCTGetEventID(event.viewTag, event.eventName, event.coalescingKey);
id<RCTEvent> previousEvent = _events[eventID];
if (previousEvent) {
event = [previousEvent coalesceWithEvent:event];
} else {
[_eventQueue addObject:eventID];
}
} else {
id<RCTEvent> previousEvent = _events[eventID];
eventID = RCTGetEventID(event.viewTag, event.eventName, RCTUniqueCoalescingKeyGenerator++);
RCTAssert(
previousEvent == nil,
@"Got event %@ which cannot be coalesced, but has the same eventID %@ as the previous event %@",
event,
eventID,
previousEvent);
[_eventQueue addObject:eventID];
}
_events[eventID] = event;
BOOL scheduleEventsDispatch = NO;
if (!_eventsDispatchScheduled) {
_eventsDispatchScheduled = YES;
scheduleEventsDispatch = YES;
}
// We have to release the lock before dispatching block with events,
// since dispatchBlock: can be executed synchronously on the same queue.
// (This is happening when chrome debugging is turned on.)
[_eventQueueLock unlock];
if (scheduleEventsDispatch) {
if (_bridge) {
[_bridge
dispatchBlock:^{
[self flushEventsQueue];
}
queue:RCTJSThread];
} else if (_dispatchToJSThread) {
_dispatchToJSThread(^{
[self flushEventsQueue];
});
}
}
}
- (void)addDispatchObserver:(id<RCTEventDispatcherObserver>)observer
{
[_observersLock lock];
[_observers addObject:observer];
[_observersLock unlock];
}
- (void)removeDispatchObserver:(id<RCTEventDispatcherObserver>)observer
{
[_observersLock lock];
[_observers removeObject:observer];
[_observersLock unlock];
}
- (void)dispatchEvent:(id<RCTEvent>)event
{
if (_bridge) {
[_bridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]];
} else {
_invokeJSWithModuleDotMethod([[event class] moduleDotMethod], [event arguments]);
}
}
- (dispatch_queue_t)methodQueue
{
return RCTJSThread;
}
// js thread only (which surprisingly can be the main thread, depends on used JS executor)
- (void)flushEventsQueue
{
[_eventQueueLock lock];
NSDictionary *events = _events;
_events = [NSMutableDictionary new];
NSMutableArray *eventQueue = _eventQueue;
_eventQueue = [NSMutableArray new];
_eventsDispatchScheduled = NO;
[_eventQueueLock unlock];
for (NSNumber *eventId in eventQueue) {
[self dispatchEvent:events[eventId]];
}
}
@end
@implementation RCTBridge (RCTEventDispatcher)
- (RCTEventDispatcher *)eventDispatcher
- (id<RCTEventDispatcherProtocol>)eventDispatcher
{
return [self moduleForClass:[RCTEventDispatcher class]];
return [self moduleForName:@"EventDispatcher" lazilyLoadIfNecessary:YES];
}
@end
@@ -10,15 +10,6 @@
#import <React/RCTBridge.h>
#import <React/RCTJSInvokerModule.h>
typedef NS_ENUM(NSInteger, RCTTextEventType) {
RCTTextEventTypeFocus,
RCTTextEventTypeBlur,
RCTTextEventTypeChange,
RCTTextEventTypeSubmit,
RCTTextEventTypeEnd,
RCTTextEventTypeKeyPress
};
/**
* The threshold at which text inputs will start warning that the JS thread
* has fallen behind (resulting in poor input performance, missed keys, etc.)
@@ -32,6 +23,15 @@ RCT_EXTERN const NSInteger RCTTextUpdateLagWarningThreshold;
*/
RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
typedef NS_ENUM(NSInteger, RCTTextEventType) {
RCTTextEventTypeFocus,
RCTTextEventTypeBlur,
RCTTextEventTypeChange,
RCTTextEventTypeSubmit,
RCTTextEventTypeEnd,
RCTTextEventTypeKeyPress
};
@protocol RCTEvent <NSObject>
@required
@@ -80,7 +80,7 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
* This class wraps the -[RCTBridge enqueueJSCall:args:] method, and
* provides some convenience methods for generating event calls.
*/
@interface RCTEventDispatcher : NSObject <RCTBridgeModule, RCTJSDispatcherModule, RCTJSInvokerModule>
@protocol RCTEventDispatcherProtocol <RCTBridgeModule, RCTJSDispatcherModule, RCTJSInvokerModule>
/**
* Deprecated, do not use.
@@ -123,6 +123,6 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
@interface RCTBridge (RCTEventDispatcher)
- (RCTEventDispatcher *)eventDispatcher;
- (id<RCTEventDispatcherProtocol>)eventDispatcher;
@end
-1
View File
@@ -15,7 +15,6 @@
#import "RCTBridge+Private.h"
#import "RCTBridge.h"
#import "RCTConstants.h"
#import "RCTEventDispatcher.h"
#import "RCTKeyCommands.h"
#import "RCTLog.h"
#import "RCTPerformanceLogger.h"
+1 -1
View File
@@ -7,7 +7,7 @@
#import <Foundation/Foundation.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
/**
* Represents a touch event, which may be composed of several touches (one for every finger).
+3 -3
View File
@@ -11,7 +11,7 @@
#import "RCTAssert.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTEventDispatcherProtocol.h"
#import "RCTLog.h"
#import "RCTSurfaceView.h"
#import "RCTTouchEvent.h"
@@ -25,7 +25,7 @@
// TODO: this class behaves a lot like a module, and could be implemented as a
// module if we were to assume that modules and RootViews had a 1:1 relationship
@implementation RCTTouchHandler {
__weak RCTEventDispatcher *_eventDispatcher;
__weak id<RCTEventDispatcherProtocol> _eventDispatcher;
/**
* Arrays managed in parallel tracking native touch object along with the
@@ -47,7 +47,7 @@
RCTAssertParam(bridge);
if ((self = [super initWithTarget:nil action:NULL])) {
_eventDispatcher = [bridge moduleForClass:[RCTEventDispatcher class]];
_eventDispatcher = bridge.eventDispatcher;
_nativeTouches = [NSMutableOrderedSet new];
_reactTouches = [NSMutableArray new];
+3
View File
@@ -117,6 +117,9 @@ rn_apple_library(
) + react_module_plugin_providers(
name = "DevSplitBundleLoader",
native_class_func = "RCTDevSplitBundleLoaderCls",
) + react_module_plugin_providers(
name = "EventDispatcher",
native_class_func = "RCTEventDispatcherCls",
),
plugins_header = "FBCoreModulesPlugins.h",
preprocessor_flags = OBJC_ARC_PREPROCESSOR_FLAGS + get_preprocessor_flags_for_build_mode() + rn_extra_build_flags() + [
+1
View File
@@ -53,6 +53,7 @@ Class RCTWebSocketExecutorCls(void) __attribute__((used));
Class RCTWebSocketModuleCls(void) __attribute__((used));
Class RCTDevLoadingViewCls(void) __attribute__((used));
Class RCTDevSplitBundleLoaderCls(void) __attribute__((used));
Class RCTEventDispatcherCls(void) __attribute__((used));
#ifdef __cplusplus
}
+1
View File
@@ -42,6 +42,7 @@ Class RCTCoreModulesClassProvider(const char *name) {
{"WebSocketModule", RCTWebSocketModuleCls},
{"DevLoadingView", RCTDevLoadingViewCls},
{"DevSplitBundleLoader", RCTDevSplitBundleLoaderCls},
{"EventDispatcher", RCTEventDispatcherCls},
};
auto p = sCoreModuleClassMap.find(name);
+1 -1
View File
@@ -10,7 +10,7 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTUIManager.h>
+1 -1
View File
@@ -10,7 +10,7 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTAssert.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTUtils.h>
#import "CoreModulesPlugins.h"
+1 -1
View File
@@ -12,7 +12,7 @@
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTProfile.h>
#import <React/RCTReloadCommand.h>
+1 -1
View File
@@ -11,7 +11,7 @@
#import <React/RCTAccessibilityManager.h>
#import <React/RCTAssert.h>
#import <React/RCTConstants.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTUIUtils.h>
#import <React/RCTUtils.h>
+17
View File
@@ -0,0 +1,17 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <UIKit/UIKit.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcherProtocol.h>
/**
* This class wraps the -[RCTBridge enqueueJSCall:args:] method, and
* provides some convenience methods for generating event calls.
*/
@interface RCTEventDispatcher : NSObject <RCTEventDispatcherProtocol>
@end
+232
View File
@@ -0,0 +1,232 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RCTEventDispatcher.h"
#import <React/RCTAssert.h>
#import <React/RCTBridge+Private.h>
#import <React/RCTBridge.h>
#import <React/RCTComponentEvent.h>
#import <React/RCTProfile.h>
#import <React/RCTUtils.h>
#import <ReactCommon/RCTTurboModule.h>
#import "CoreModulesPlugins.h"
static NSNumber *RCTGetEventID(NSNumber *viewTag, NSString *eventName, uint16_t coalescingKey)
{
return @(viewTag.intValue | (((uint64_t)eventName.hash & 0xFFFF) << 32) | (((uint64_t)coalescingKey) << 48));
}
static uint16_t RCTUniqueCoalescingKeyGenerator = 0;
@interface RCTEventDispatcher () <RCTTurboModule>
@end
@implementation RCTEventDispatcher {
// We need this lock to protect access to _events, _eventQueue and _eventsDispatchScheduled. It's filled in on main
// thread and consumed on js thread.
NSLock *_eventQueueLock;
// We have this id -> event mapping so we coalesce effectively.
NSMutableDictionary<NSNumber *, id<RCTEvent>> *_events;
// This array contains ids of events in order they come in, so we can emit them to JS in the exact same order.
NSMutableArray<NSNumber *> *_eventQueue;
BOOL _eventsDispatchScheduled;
NSHashTable<id<RCTEventDispatcherObserver>> *_observers;
NSLock *_observersLock;
}
@synthesize bridge = _bridge;
@synthesize dispatchToJSThread = _dispatchToJSThread;
@synthesize invokeJS = _invokeJS;
@synthesize invokeJSWithModuleDotMethod = _invokeJSWithModuleDotMethod;
RCT_EXPORT_MODULE()
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
_events = [NSMutableDictionary new];
_eventQueue = [NSMutableArray new];
_eventQueueLock = [NSLock new];
_eventsDispatchScheduled = NO;
_observers = [NSHashTable weakObjectsHashTable];
_observersLock = [NSLock new];
}
- (void)sendAppEventWithName:(NSString *)name body:(id)body
{
if (_bridge) {
[_bridge enqueueJSCall:@"RCTNativeAppEventEmitter"
method:@"emit"
args:body ? @[ name, body ] : @[ name ]
completion:NULL];
} else {
_invokeJS(@"RCTNativeAppEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]);
}
}
- (void)sendDeviceEventWithName:(NSString *)name body:(id)body
{
if (_bridge) {
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter"
method:@"emit"
args:body ? @[ name, body ] : @[ name ]
completion:NULL];
} else {
_invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ name, body ] : @[ name ]);
}
}
- (void)sendTextEventWithType:(RCTTextEventType)type
reactTag:(NSNumber *)reactTag
text:(NSString *)text
key:(NSString *)key
eventCount:(NSInteger)eventCount
{
static NSString *events[] = {@"focus", @"blur", @"change", @"submitEditing", @"endEditing", @"keyPress"};
NSMutableDictionary *body = [[NSMutableDictionary alloc] initWithDictionary:@{
@"eventCount" : @(eventCount),
}];
if (text) {
body[@"text"] = text;
}
if (key) {
if (key.length == 0) {
key = @"Backspace"; // backspace
} else {
switch ([key characterAtIndex:0]) {
case '\t':
key = @"Tab";
break;
case '\n':
key = @"Enter";
default:
break;
}
}
body[@"key"] = key;
}
RCTComponentEvent *event = [[RCTComponentEvent alloc] initWithName:events[type] viewTag:reactTag body:body];
[self sendEvent:event];
}
- (void)sendEvent:(id<RCTEvent>)event
{
[_observersLock lock];
for (id<RCTEventDispatcherObserver> observer in _observers) {
[observer eventDispatcherWillDispatchEvent:event];
}
[_observersLock unlock];
[_eventQueueLock lock];
NSNumber *eventID;
if (event.canCoalesce) {
eventID = RCTGetEventID(event.viewTag, event.eventName, event.coalescingKey);
id<RCTEvent> previousEvent = _events[eventID];
if (previousEvent) {
event = [previousEvent coalesceWithEvent:event];
} else {
[_eventQueue addObject:eventID];
}
} else {
id<RCTEvent> previousEvent = _events[eventID];
eventID = RCTGetEventID(event.viewTag, event.eventName, RCTUniqueCoalescingKeyGenerator++);
RCTAssert(
previousEvent == nil,
@"Got event %@ which cannot be coalesced, but has the same eventID %@ as the previous event %@",
event,
eventID,
previousEvent);
[_eventQueue addObject:eventID];
}
_events[eventID] = event;
BOOL scheduleEventsDispatch = NO;
if (!_eventsDispatchScheduled) {
_eventsDispatchScheduled = YES;
scheduleEventsDispatch = YES;
}
// We have to release the lock before dispatching block with events,
// since dispatchBlock: can be executed synchronously on the same queue.
// (This is happening when chrome debugging is turned on.)
[_eventQueueLock unlock];
if (scheduleEventsDispatch) {
if (_bridge) {
[_bridge
dispatchBlock:^{
[self flushEventsQueue];
}
queue:RCTJSThread];
} else if (_dispatchToJSThread) {
_dispatchToJSThread(^{
[self flushEventsQueue];
});
}
}
}
- (void)addDispatchObserver:(id<RCTEventDispatcherObserver>)observer
{
[_observersLock lock];
[_observers addObject:observer];
[_observersLock unlock];
}
- (void)removeDispatchObserver:(id<RCTEventDispatcherObserver>)observer
{
[_observersLock lock];
[_observers removeObject:observer];
[_observersLock unlock];
}
- (void)dispatchEvent:(id<RCTEvent>)event
{
if (_bridge) {
[_bridge enqueueJSCall:[[event class] moduleDotMethod] args:[event arguments]];
} else {
_invokeJSWithModuleDotMethod([[event class] moduleDotMethod], [event arguments]);
}
}
- (dispatch_queue_t)methodQueue
{
return RCTJSThread;
}
// js thread only (which surprisingly can be the main thread, depends on used JS executor)
- (void)flushEventsQueue
{
[_eventQueueLock lock];
NSDictionary *events = _events;
_events = [NSMutableDictionary new];
NSMutableArray *eventQueue = _eventQueue;
_eventQueue = [NSMutableArray new];
_eventsDispatchScheduled = NO;
[_eventQueueLock unlock];
for (NSNumber *eventId in eventQueue) {
[self dispatchEvent:events[eventId]];
}
}
@end
Class RCTEventDispatcherCls(void)
{
return RCTEventDispatcher.class;
}
+1 -1
View File
@@ -8,7 +8,7 @@
#import "RCTKeyboardObserver.h"
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import "CoreModulesPlugins.h"
+1 -1
View File
@@ -12,7 +12,7 @@
#import <React/RCTConvert.h>
#import <React/RCTDefines.h>
#import <React/RCTErrorInfo.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTJSStackFrame.h>
#import <React/RCTRedBoxExtraDataViewController.h>
#import <React/RCTRedBoxSetEnabled.h>
+1 -1
View File
@@ -8,7 +8,7 @@
#import "RCTStatusBarManager.h"
#import "CoreModulesPlugins.h"
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTUtils.h>
+1 -1
View File
@@ -17,7 +17,7 @@
#import "RCTComponentData.h"
#import "RCTConvert.h"
#import "RCTDefines.h"
#import "RCTEventDispatcher.h"
#import "RCTEventDispatcherProtocol.h"
#import "RCTLayoutAnimation.h"
#import "RCTLayoutAnimationGroup.h"
#import "RCTLog.h"
-1
View File
@@ -10,7 +10,6 @@
#import <React/RCTUIManager.h>
#import "RCTBridge.h"
#import "RCTDatePicker.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
@implementation RCTConvert (UIDatePicker)
-1
View File
@@ -8,7 +8,6 @@
#import "RCTSegmentedControl.h"
#import "RCTConvert.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
@implementation RCTSegmentedControl
-1
View File
@@ -8,7 +8,6 @@
#import "RCTSliderManager.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTSlider.h"
#import "UIView+React.h"
-1
View File
@@ -7,7 +7,6 @@
#import "RCTSwitch.h"
#import "RCTEventDispatcher.h"
#import "UIView+React.h"
@implementation RCTSwitch
-1
View File
@@ -9,7 +9,6 @@
#import <React/RCTUIManager.h>
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
#import "RCTSwitch.h"
#import "UIView+React.h"
+1 -1
View File
@@ -10,7 +10,7 @@
#import <React/RCTBridgeModule.h>
#import <React/RCTConvert.h>
#import <React/RCTDefines.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/UIView+React.h>
-1
View File
@@ -11,7 +11,6 @@
#import "RCTBridge.h"
#import "RCTConvert+Transform.h"
#import "RCTConvert.h"
#import "RCTEventDispatcher.h"
#import "RCTLog.h"
#import "RCTShadowView.h"
#import "RCTUIManager.h"
-2
View File
@@ -10,14 +10,12 @@
#import <UIKit/UIScrollView.h>
#import "RCTAutoInsetsProtocol.h"
#import "RCTEventDispatcher.h"
#import "RCTUtils.h"
#import "UIView+React.h"
@implementation RCTWrapperViewController {
UIView *_wrapperView;
UIView *_contentView;
RCTEventDispatcher *_eventDispatcher;
CGFloat _previousTopLayoutLength;
CGFloat _previousBottomLayoutLength;
+1 -1
View File
@@ -6,7 +6,7 @@
*/
#import <Foundation/Foundation.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
@interface RCTScrollEvent : NSObject <RCTEvent>
+4 -10
View File
@@ -8,7 +8,8 @@
#import <UIKit/UIScrollView.h>
#import <React/RCTAutoInsetsProtocol.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTDefines.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTScrollableProtocol.h>
#import <React/RCTView.h>
@@ -16,7 +17,7 @@
@interface RCTScrollView : RCTView <UIScrollViewDelegate, RCTScrollableProtocol, RCTAutoInsetsProtocol>
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher NS_DESIGNATED_INITIALIZER;
/**
* The `RCTScrollView` may have at most one single subview. This will ensure
@@ -71,11 +72,4 @@
@end
@interface RCTEventDispatcher (RCTScrollView)
/**
* Send a fake scroll event.
*/
- (void)sendFakeScrollEvent:(NSNumber *)reactTag;
@end
RCT_EXTERN void RCTSendFakeScrollEvent(id<RCTEventDispatcherProtocol> eventDispatcher, NSNumber *reactTag);
+4 -8
View File
@@ -261,7 +261,7 @@
@end
@implementation RCTScrollView {
RCTEventDispatcher *_eventDispatcher;
id<RCTEventDispatcherProtocol> _eventDispatcher;
CGRect _prevFirstVisibleFrame;
__weak UIView *_firstVisibleView;
RCTCustomScrollView *_scrollView;
@@ -275,7 +275,7 @@
NSHashTable *_scrollListeners;
}
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher
{
RCTAssertParam(eventDispatcher);
@@ -1022,9 +1022,7 @@ RCT_SET_AND_PRESERVE_OFFSET(setScrollIndicatorInsets, scrollIndicatorInsets, UIE
@end
@implementation RCTEventDispatcher (RCTScrollView)
- (void)sendFakeScrollEvent:(NSNumber *)reactTag
void RCTSendFakeScrollEvent(id<RCTEventDispatcherProtocol> eventDispatcher, NSNumber *reactTag)
{
// Use the selector here in case the onScroll block property is ever renamed
NSString *eventName = NSStringFromSelector(@selector(onScroll));
@@ -1037,7 +1035,5 @@ RCT_SET_AND_PRESERVE_OFFSET(setScrollIndicatorInsets, scrollIndicatorInsets, UIE
scrollViewZoomScale:0
userData:nil
coalescingKey:0];
[self sendEvent:fakeScrollEvent];
[eventDispatcher sendEvent:fakeScrollEvent];
}
@end
@@ -9,6 +9,7 @@
#include <React/RCTBridge+Private.h>
#include <React/RCTBridgeMethod.h>
#include <React/RCTComponentData.h>
#include <React/RCTEventDispatcherProtocol.h>
#include <React/RCTFollyConvert.h>
#include <React/RCTModuleData.h>
#include <React/RCTUIManager.h>
+1 -1
View File
@@ -8,7 +8,7 @@
#import "RCTTestModule.h"
#import <React/RCTAssert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTLog.h>
#import <React/RCTUIManager.h>
#import <ReactCommon/RCTTurboModule.h>
@@ -9,7 +9,7 @@
#import <XCTest/XCTest.h>
#import <RCTTest/RCTTestRunner.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTEventDispatcherProtocol.h>
#import <React/RCTRootView.h>
#import <React/RCTRootViewDelegate.h>