mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add support to register New Renderer components from the AppDelegate. (#37273)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/37273 When using dynamic frameworks, we can't rely on Codegen to register all the components into the renderer. That's because, we would have to codegen a new target, which depends on ALL the 3rd party dependencies that expose a UI component. The previous PR adds support for distributed automatic registration when components are loaded in memory. However, not to slow down the adoption of the New Architecture, there could be apps that need to register a component that does not support the distributed approach yet. Thanks to this method, apps can register those components. ## Changelog: [iOS][Added] - Added a mechanism to register components into the renderer from the user app. Reviewed By: dmytrorykun Differential Revision: D45605688 fbshipit-source-id: 3583913f2700be4d6cb33a862429486aca675acf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b6b09a7e72
commit
ce116b653b
@@ -9,6 +9,7 @@
|
||||
#import <React/RCTBridgeDelegate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@protocol RCTComponentViewProtocol;
|
||||
@class RCTSurfacePresenterBridgeAdapter;
|
||||
|
||||
/**
|
||||
@@ -96,6 +97,14 @@
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
@property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter;
|
||||
|
||||
/// This method returns a map of Component Descriptors and Components classes that needs to be registered in the
|
||||
/// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native
|
||||
/// component. The default implementation returns an empty dictionary. Subclasses can override this method to register
|
||||
/// the required components.
|
||||
///
|
||||
/// @return a dictionary that associate a component for the new renderer with his descriptor.
|
||||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;
|
||||
|
||||
/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off.
|
||||
///
|
||||
/// @note: This is required to be rendering on Fabric (i.e. on the New Architecture).
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <React/CoreModulesPlugins.h>
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
#import <React/RCTComponentViewProtocol.h>
|
||||
#import <React/RCTCxxBridgeDelegate.h>
|
||||
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
||||
#import <React/RCTLegacyViewManagerInteropComponentView.h>
|
||||
@@ -24,7 +26,10 @@
|
||||
|
||||
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
|
||||
@interface RCTAppDelegate () <RCTTurboModuleManagerDelegate, RCTCxxBridgeDelegate> {
|
||||
@interface RCTAppDelegate () <
|
||||
RCTTurboModuleManagerDelegate,
|
||||
RCTCxxBridgeDelegate,
|
||||
RCTComponentViewFactoryComponentProvider> {
|
||||
std::shared_ptr<const facebook::react::ReactNativeConfig> _reactNativeConfig;
|
||||
facebook::react::ContextContainer::Shared _contextContainer;
|
||||
std::shared_ptr<facebook::react::RuntimeScheduler> _runtimeScheduler;
|
||||
@@ -64,6 +69,7 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter;
|
||||
|
||||
[self unstable_registerLegacyComponents];
|
||||
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
|
||||
#endif
|
||||
|
||||
NSDictionary *initProps = [self prepareInitialProps];
|
||||
@@ -163,6 +169,13 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
return RCTAppSetupDefaultModuleFromClass(moduleClass);
|
||||
}
|
||||
|
||||
#pragma mark - RCTComponentViewFactoryComponentProvider
|
||||
|
||||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
|
||||
{
|
||||
return @{};
|
||||
}
|
||||
|
||||
#pragma mark - New Arch Enabled settings
|
||||
|
||||
- (BOOL)turboModuleEnabled
|
||||
|
||||
@@ -16,12 +16,28 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
void RCTInstallNativeComponentRegistryBinding(facebook::jsi::Runtime &runtime);
|
||||
|
||||
/**
|
||||
* Protocol that can be implemented to provide some 3rd party components to Fabric.
|
||||
* Fabric will check in this map whether there are some components that need to be registered.
|
||||
*/
|
||||
@protocol RCTComponentViewFactoryComponentProvider <NSObject>
|
||||
|
||||
/**
|
||||
* Return a dictionary of third party components where the `key` is the Component Handler and the `value` is a Class
|
||||
* that conforms to `RCTComponentViewProtocol`.
|
||||
*/
|
||||
- (NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Registry of supported component view classes that can instantiate
|
||||
* view component instances by given component handle.
|
||||
*/
|
||||
@interface RCTComponentViewFactory : NSObject
|
||||
|
||||
@property (nonatomic, weak) id<RCTComponentViewFactoryComponentProvider> thirdPartyFabricComponentsProvider;
|
||||
|
||||
/**
|
||||
* Constructs and returns an instance of the class with a bunch of already registered standard components.
|
||||
*/
|
||||
|
||||
@@ -112,7 +112,19 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Fallback 2: Try to use Paper Interop.
|
||||
// Fallback 2: Ask the provider and check in the dictionary provided
|
||||
if (self.thirdPartyFabricComponentsProvider) {
|
||||
// Test whether a provider has been passed to avoid potentially expensive conversions
|
||||
// between C++ and ObjC strings.
|
||||
NSString *objcName = [NSString stringWithCString:name.c_str() encoding:NSUTF8StringEncoding];
|
||||
klass = self.thirdPartyFabricComponentsProvider.thirdPartyFabricComponents[objcName];
|
||||
if (klass) {
|
||||
[self registerComponentViewClass:klass];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback 3: Try to use Paper Interop.
|
||||
NSString *componentNameString = RCTNSStringFromString(name);
|
||||
if ([RCTLegacyViewManagerInteropComponentView isSupported:componentNameString]) {
|
||||
RCTLogNewArchitectureValidation(
|
||||
@@ -136,7 +148,7 @@ static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Fallback 3: use <UnimplementedView> if component doesn't exist.
|
||||
// Fallback 4: use <UnimplementedView> if component doesn't exist.
|
||||
auto flavor = std::make_shared<std::string const>(name);
|
||||
auto componentName = ComponentName{flavor->c_str()};
|
||||
auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
|
||||
|
||||
@@ -70,7 +70,6 @@ class NewArchitectureHelper
|
||||
# Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic
|
||||
# This helps with backward compatibility.
|
||||
if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic'
|
||||
Pod::UI.puts "Adding RCT_DYNAMIC_FRAMEWORKS=1 to React-RCTFabric".yellow
|
||||
rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1"
|
||||
target_installation_result.native_target.build_configurations.each do |config|
|
||||
prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)"
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
#import <React/RCTComponentViewFactory.h>
|
||||
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
|
||||
#import <React/RCTSurfacePresenter.h>
|
||||
#import <React/RCTSurfacePresenterBridgeAdapter.h>
|
||||
@@ -60,6 +61,10 @@
|
||||
#import <react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h>
|
||||
#endif
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
#import <RNTMyNativeViewComponentView.h>
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
#ifdef FB_SONARKIT_ENABLED
|
||||
#import <FlipperKit/FlipperClient.h>
|
||||
@@ -85,6 +90,12 @@
|
||||
}
|
||||
@end
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
/// Declare conformance to `RCTComponentViewFactoryComponentProvider`
|
||||
@interface AppDelegate () <RCTComponentViewFactoryComponentProvider>
|
||||
@end
|
||||
#endif
|
||||
|
||||
static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
|
||||
@implementation AppDelegate
|
||||
@@ -110,6 +121,10 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
// Appetizer.io params check
|
||||
NSDictionary *initProps = [self prepareInitialProps];
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
[RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self;
|
||||
#endif
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
_bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:_bridge contextContainer:_contextContainer];
|
||||
|
||||
@@ -333,4 +348,13 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - RCTComponentViewFactoryComponentProvider
|
||||
|
||||
#if RCT_NEW_ARCH_ENABLED
|
||||
- (nonnull NSDictionary<NSString *, Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents
|
||||
{
|
||||
return @{@"RNTMyNativeView" : RNTMyNativeViewComponentView.class};
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user