From a28881a3d79e732670157638aa5207c88c79718c Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 27 Jun 2023 08:43:23 -0700 Subject: [PATCH] Implement multiple manager lookup for the interop layer (#38093) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/38093 In [this issue](https://github.com/facebook/react-native/issues/37905), the community detected a strict assumption in the interop layer for which, given a component `XXXView`, its ViewManager must be called `RCTXXXViewManager`. That's not the case for some components, for example, `BVLinearGradient`, which View manager is `BVLinearGradientManager` and not `RCTBVLinearGradientManager`. This diff adds a secondary lookup logic: 1. We look for the `RCTXXXViewManager`. 2. If not found, we look for `XXXViewManager`. We will assess whether to generalize this logic once and for all or to expand other lookup cases on an example/failure basis as it's not a goal to have a 100% accurate interop layer. The Goal is to cover most use cases. ## Changelog: [iOS][Added] - Allow to lookup for ViewManager without the RCT prefix in the Interop Layer Reviewed By: sammy-SC Differential Revision: D47055969 fbshipit-source-id: 1d31f3f4bc6f1f543edbd157ce04ad9daf23dbc6 --- ...cyViewManagerInteropComponentDescriptor.mm | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm index 4df8893ba2ff62..c8e2c07d0191e4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropComponentDescriptor.mm @@ -18,7 +18,7 @@ namespace facebook::react { -static std::string moduleNameFromComponentName(const std::string &componentName) +static std::string moduleNameFromComponentNameNoRCTPrefix(const std::string &componentName) { // TODO: remove FB specific code (T56174424) if (componentName == "StickerInputView") { @@ -45,22 +45,41 @@ return componentName + "Manager"; } - return "RCT" + componentName + "Manager"; + return componentName + "Manager"; } inline NSString *RCTNSStringFromString(const std::string &string) { - return [NSString stringWithCString:string.c_str() encoding:NSUTF8StringEncoding]; + return [NSString stringWithUTF8String:string.c_str()]; +} + +static Class getViewManagerFromComponentName(const std::string &componentName) +{ + auto viewManagerName = moduleNameFromComponentNameNoRCTPrefix(componentName); + + // 1. Try to get the manager with the RCT prefix. + auto rctViewManagerName = "RCT" + viewManagerName; + Class viewManagerClass = NSClassFromString(RCTNSStringFromString(rctViewManagerName)); + if (viewManagerClass) { + return viewManagerClass; + } + + // 2. Try to get the manager without the prefix. + viewManagerClass = NSClassFromString(RCTNSStringFromString(viewManagerName)); + if (viewManagerClass) { + return viewManagerClass; + } + + return nil; } static std::shared_ptr const constructCoordinator( ContextContainer::Shared const &contextContainer, ComponentDescriptor::Flavor const &flavor) { - auto &componentName = *static_cast(flavor.get()); - auto moduleName = moduleNameFromComponentName(componentName); - Class module = NSClassFromString(RCTNSStringFromString(moduleName)); - assert(module); + auto componentName = *std::static_pointer_cast(flavor); + Class viewManagerClass = getViewManagerFromComponentName(componentName); + assert(viewManagerClass); auto optionalBridge = contextContainer->find>("Bridge"); RCTBridge *bridge; if (optionalBridge) { @@ -79,7 +98,7 @@ bridgeModuleDecorator = unwrapManagedObject(optionalModuleDecorator.value()); } - RCTComponentData *componentData = [[RCTComponentData alloc] initWithManagerClass:module + RCTComponentData *componentData = [[RCTComponentData alloc] initWithManagerClass:viewManagerClass bridge:bridge eventDispatcher:eventDispatcher]; return wrapManagedObject([[RCTLegacyViewManagerInteropCoordinator alloc]