From fced0765d6162ddf2de4b9afdd1877b6d2b204f9 Mon Sep 17 00:00:00 2001 From: Ramanpreet Nara Date: Sat, 19 Dec 2020 05:59:22 -0800 Subject: [PATCH] Introduce RCTViewRegistry Summary: ## Problem Many of our NativeModules use the bridge to access the UIManager. They then use the UIManager to call viewForReactTag. This makes all these NativeModules Venice-incompatible. P155700869 ## Solution This diff introduces a Venice-compatible API called RCTViewRegistry that will implement viewForReactTag. When the bridge exists, RCTViewRegistry will delegate to the UIManager. When the bridge doesn't exist, it'll delegate to RCTSurfacePresenter. Fingers crossed, this should allow us move ~50 NativeModuels off the bridge. Changelog: [Internal] Reviewed By: PeteTheHeat Differential Revision: D25641391 fbshipit-source-id: 144f4f7a35af1245401ad640068852dd66bbf65d --- React/Base/RCTBridgeModule.h | 25 ++++++++++++++++++++ React/Base/RCTViewRegistry.m | 45 ++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 React/Base/RCTViewRegistry.m diff --git a/React/Base/RCTBridgeModule.h b/React/Base/RCTBridgeModule.h index e4bbef2a1a7..b8d3ea6ee71 100644 --- a/React/Base/RCTBridgeModule.h +++ b/React/Base/RCTBridgeModule.h @@ -6,12 +6,14 @@ */ #import +#import #import @class RCTBridge; @protocol RCTBridgeMethod; @class RCTModuleRegistry; +@class RCTViewRegistry; /** * The type of a block that is capable of sending a response to a bridged @@ -122,6 +124,17 @@ RCT_EXTERN_C_END */ @property (nonatomic, weak, readonly) RCTModuleRegistry *moduleRegistry; +/** + * A reference to the RCTViewRegistry. Useful for modules that query UIViews, + * given a react tag. This API is deprecated, and only exists to help migrate + * NativeModules to Venice. + * + * To implement this in your module, just add `@synthesize + * viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED;`. If using Swift, add + * `@objc var viewRegistry_DEPRECATED: RCTViewRegistry!` to your module. + */ +@property (nonatomic, weak, readonly) RCTViewRegistry *viewRegistry_DEPRECATED; + /** * A reference to the RCTBridge. Useful for modules that require access * to bridge features, such as sending events or making JS calls. This @@ -392,3 +405,15 @@ RCT_EXTERN_C_END - (id)moduleForName:(const char *)moduleName; - (id)moduleForName:(const char *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; @end + +typedef UIView * (^RCTBridgelessComponentViewProvider)(NSNumber *); + +/** + * A class that allows NativeModules to query for views, given React Tags. + */ +@interface RCTViewRegistry : NSObject +- (void)setBridge:(RCTBridge *)bridge; +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)bridgelessComponentViewProvider; + +- (UIView *)viewForReactTag:(NSNumber *)reactTag; +@end diff --git a/React/Base/RCTViewRegistry.m b/React/Base/RCTViewRegistry.m new file mode 100644 index 00000000000..d66caa17bb6 --- /dev/null +++ b/React/Base/RCTViewRegistry.m @@ -0,0 +1,45 @@ +/* + * 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 +#import + +#import "RCTBridge.h" +#import "RCTBridgeModule.h" + +@implementation RCTViewRegistry { + RCTBridgelessComponentViewProvider _bridgelessComponentViewProvider; + __weak RCTBridge *_bridge; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + _bridge = bridge; +} + +- (void)setBridgelessComponentViewProvider:(RCTBridgelessComponentViewProvider)bridgelessComponentViewProvider +{ + _bridgelessComponentViewProvider = bridgelessComponentViewProvider; +} + +- (UIView *)viewForReactTag:(NSNumber *)reactTag +{ + UIView *view = nil; + + RCTBridge *bridge = _bridge; + if (bridge) { + view = [bridge.uiManager viewForReactTag:reactTag]; + } + + if (view == nil && _bridgelessComponentViewProvider) { + view = _bridgelessComponentViewProvider(reactTag); + } + + return view; +} + +@end