mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Handle commands in RCTLegacyViewManagerInteropCoordinator [3/n]
Summary: Problem: `RCTLegacyViewManagerInteropCoordinator.mm` handles view commands by looking up `RCTModuleData` from the bridge, and then dispatching that method. In bridgeless mode, `RCTModuleData` doesn't exist. Solution: Instead of relying on `RCTModuleData` (which does a ton of things), manually create a `_moduleMethods` array to store the methods that view manager exposes. This manual creation code was copied from how `RCTModuleData` performs lookup. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D27377257 fbshipit-source-id: c3e820808e6aca03bae6486d5510156b39462215
This commit is contained in:
committed by
Facebook GitHub Bot
parent
491ca1d14e
commit
10acccc86d
+58
-9
@@ -12,10 +12,12 @@
|
||||
#include <React/RCTEventDispatcherProtocol.h>
|
||||
#include <React/RCTFollyConvert.h>
|
||||
#include <React/RCTModuleData.h>
|
||||
#include <React/RCTModuleMethod.h>
|
||||
#include <React/RCTUIManager.h>
|
||||
#include <React/RCTUIManagerUtils.h>
|
||||
#include <React/RCTUtils.h>
|
||||
#include <folly/json.h>
|
||||
#include <objc/runtime.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@@ -23,13 +25,20 @@ using namespace facebook::react;
|
||||
RCTComponentData *_componentData;
|
||||
__weak RCTBridge *_bridge;
|
||||
/*
|
||||
Each instnace of `RCTLegacyViewManagerInteropComponentView` registers a block to which events are dispatched.
|
||||
Each instance of `RCTLegacyViewManagerInteropComponentView` registers a block to which events are dispatched.
|
||||
This is the container that maps unretained UIView pointer to a block to which the event is dispatched.
|
||||
*/
|
||||
NSMutableDictionary<NSNumber *, InterceptorBlock> *_eventInterceptors;
|
||||
|
||||
/*
|
||||
* In bridgeless mode, instead of using the bridge to look up RCTModuleData,
|
||||
* store that information locally.
|
||||
*/
|
||||
NSMutableArray<id<RCTBridgeMethod>> *_moduleMethods;
|
||||
NSMutableDictionary<NSString *, id<RCTBridgeMethod>> *_moduleMethodsByName;
|
||||
}
|
||||
|
||||
- (instancetype)initWithComponentData:(RCTComponentData *)componentData bridge:(RCTBridge *)bridge;
|
||||
- (instancetype)initWithComponentData:(RCTComponentData *)componentData bridge:(RCTBridge *)bridge
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_componentData = componentData;
|
||||
@@ -81,12 +90,13 @@ using namespace facebook::react;
|
||||
- (void)handleCommand:(NSString *)commandName args:(NSArray *)args reactTag:(NSInteger)tag
|
||||
{
|
||||
Class managerClass = _componentData.managerClass;
|
||||
[self _lookupModuleMethodsIfNecessary];
|
||||
RCTModuleData *moduleData = [_bridge.batchedBridge moduleDataForName:RCTBridgeModuleNameForClass(managerClass)];
|
||||
id<RCTBridgeMethod> method;
|
||||
if ([commandName isKindOfClass:[NSNumber class]]) {
|
||||
method = moduleData.methods[[commandName intValue]];
|
||||
method = moduleData ? moduleData.methods[[commandName intValue]] : _moduleMethods[[commandName intValue]];
|
||||
} else if ([commandName isKindOfClass:[NSString class]]) {
|
||||
method = moduleData.methodsByName[commandName];
|
||||
method = moduleData ? moduleData.methodsByName[commandName] : _moduleMethodsByName[commandName];
|
||||
if (method == nil) {
|
||||
RCTLogError(@"No command found with name \"%@\"", commandName);
|
||||
}
|
||||
@@ -96,12 +106,51 @@ using namespace facebook::react;
|
||||
}
|
||||
|
||||
NSArray *newArgs = [@[ [NSNumber numberWithInteger:tag] ] arrayByAddingObjectsFromArray:args];
|
||||
[_bridge.batchedBridge
|
||||
dispatchBlock:^{
|
||||
[method invokeWithBridge:self->_bridge module:self->_componentData.manager arguments:newArgs];
|
||||
[self->_bridge.uiManager setNeedsLayout];
|
||||
|
||||
if (_bridge) {
|
||||
[_bridge.batchedBridge
|
||||
dispatchBlock:^{
|
||||
[method invokeWithBridge:self->_bridge module:self->_componentData.manager arguments:newArgs];
|
||||
[self->_bridge.uiManager setNeedsLayout];
|
||||
}
|
||||
queue:RCTGetUIManagerQueue()];
|
||||
} else {
|
||||
// TODO T86826778 - Figure out which queue this should be dispatched to.
|
||||
[method invokeWithBridge:nil module:self->_componentData.manager arguments:newArgs];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
// This is copy-pasta from RCTModuleData.
|
||||
- (void)_lookupModuleMethodsIfNecessary
|
||||
{
|
||||
if (!_bridge && !_moduleMethods) {
|
||||
_moduleMethods = [NSMutableArray new];
|
||||
_moduleMethodsByName = [NSMutableDictionary new];
|
||||
|
||||
unsigned int methodCount;
|
||||
Class cls = _componentData.managerClass;
|
||||
while (cls && cls != [NSObject class] && cls != [NSProxy class]) {
|
||||
Method *methods = class_copyMethodList(object_getClass(cls), &methodCount);
|
||||
|
||||
for (unsigned int i = 0; i < methodCount; i++) {
|
||||
Method method = methods[i];
|
||||
SEL selector = method_getName(method);
|
||||
if ([NSStringFromSelector(selector) hasPrefix:@"__rct_export__"]) {
|
||||
IMP imp = method_getImplementation(method);
|
||||
auto exportedMethod = ((const RCTMethodInfo *(*)(id, SEL))imp)(_componentData.managerClass, selector);
|
||||
id<RCTBridgeMethod> moduleMethod =
|
||||
[[RCTModuleMethod alloc] initWithExportedMethod:exportedMethod moduleClass:_componentData.managerClass];
|
||||
[_moduleMethodsByName setValue:moduleMethod forKey:[NSString stringWithUTF8String:moduleMethod.JSMethodName]];
|
||||
[_moduleMethods addObject:moduleMethod];
|
||||
}
|
||||
}
|
||||
queue:RCTGetUIManagerQueue()];
|
||||
|
||||
free(methods);
|
||||
cls = class_getSuperclass(cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user