From 4efdf264d1129af16b91bee4f92aa9d5e82bfbf2 Mon Sep 17 00:00:00 2001 From: Peter Argany Date: Wed, 31 Mar 2021 16:37:02 -0700 Subject: [PATCH] Introducing RCTWeakViewHolder [4/n] Summary: Problem: In paper, there is a handy API called `[uiManager viewForReactTag:]`. Fabric does not have this mapping. The Fabric interop layer still relies on this Paper mapping. Solution: As a workaround, re-create this mapping in the Fabric interop layer. Therefore, whenever Fabric interop layer asks a paper view manager to create a view, store a weak reference to the view in a `NSMapTable`. NSMapTable allows us to customize the strong/weak relationship. I've added a comment explaining that `RCTWeakViewHolder` only needs to be used for this special circumstance. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D27438899 fbshipit-source-id: 94663ef06479a8c863ce58b0f36d42109fa1c4f3 --- ...acyViewManagerInteropCoordinatorAdapter.mm | 4 +--- React/Views/RCTWeakViewHolder.h | 19 +++++++++++++++++++ .../RCTLegacyViewManagerInteropCoordinator.h | 2 +- .../RCTLegacyViewManagerInteropCoordinator.mm | 14 +++++++++++--- 4 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 React/Views/RCTWeakViewHolder.h diff --git a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm index 31d505630fa..15980bcfd9f 100644 --- a/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm +++ b/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropCoordinatorAdapter.mm @@ -31,9 +31,7 @@ - (UIView *)paperView { if (!_paperView) { - _paperView = _coordinator.paperView; - _paperView.reactTag = [NSNumber numberWithInteger:_tag]; - + _paperView = [_coordinator createPaperViewWithTag:_tag]; __weak __typeof(self) weakSelf = self; [_coordinator addObserveForTag:_tag usingBlock:^(std::string eventName, folly::dynamic event) { diff --git a/React/Views/RCTWeakViewHolder.h b/React/Views/RCTWeakViewHolder.h new file mode 100644 index 00000000000..ce39eee5d38 --- /dev/null +++ b/React/Views/RCTWeakViewHolder.h @@ -0,0 +1,19 @@ +/* + * 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. + */ + +/* + * THIS IS A HACK + * This protocol should only be used for Paper ViewManagers which need to + * use the Fabric Interop layer, and also need to reference their created + * views. This protocol allows the view manager to store a weak reference to + * any created views. It will not affect view lifecycle in any way. + */ +@protocol RCTWeakViewHolder + +@property (nonatomic, strong) NSMapTable *weakViews; + +@end diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h index f93f9592839..ca84249cae9 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.h @@ -20,7 +20,7 @@ typedef void (^InterceptorBlock)(std::string eventName, folly::dynamic event); - (instancetype)initWithComponentData:(RCTComponentData *)componentData bridge:(RCTBridge *)bridge; -- (UIView *)paperView; +- (UIView *)createPaperViewWithTag:(NSInteger)tag; - (void)addObserveForTag:(NSInteger)tag usingBlock:(InterceptorBlock)block; diff --git a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm index e651dfc4638..60ac9786f65 100644 --- a/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm +++ b/ReactCommon/react/renderer/components/legacyviewmanagerinterop/RCTLegacyViewManagerInteropCoordinator.mm @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -70,10 +71,17 @@ using namespace facebook::react; [_eventInterceptors removeObjectForKey:[NSNumber numberWithInteger:tag]]; } -- (UIView *)paperView +- (UIView *)createPaperViewWithTag:(NSInteger)tag; { - // TODO: pass in the right tags? - return [_componentData createViewWithTag:NULL rootTag:NULL]; + UIView *view = [_componentData createViewWithTag:[NSNumber numberWithInteger:tag] rootTag:NULL]; + if ([_componentData.bridgelessViewManager conformsToProtocol:@protocol(RCTWeakViewHolder)]) { + id weakViewHolder = (id)_componentData.bridgelessViewManager; + if (!weakViewHolder.weakViews) { + weakViewHolder.weakViews = [NSMapTable strongToWeakObjectsMapTable]; + } + [weakViewHolder.weakViews setObject:view forKey:[NSNumber numberWithInteger:tag]]; + } + return view; } - (void)setProps:(folly::dynamic const &)props forView:(UIView *)view