RCTShadowView have got rootView property

Summary:
We have to have a way to track ownership of shadow view.
Previous solution with traversing the hierarchy to figure out the root view does not actually work in some cases when the view is temporary detached from hierarchy.
This is also how it work on Andorid.

Reviewed By: mmmulani

Differential Revision: D5686112

fbshipit-source-id: a23a10e8c29c7572ac69403289db136c9d5176a9
This commit is contained in:
Valentin Shergin 2017-08-23 23:44:01 -07:00 committed by Facebook Github Bot
parent e6ff0dacd5
commit 6493a85754
6 changed files with 57 additions and 25 deletions

View File

@ -11,6 +11,8 @@
#import <XCTest/XCTest.h>
#import <RCTTest/RCTTestRunner.h>
#import <React/RCTRootShadowView.h>
#import <React/RCTShadowView.h>
#import <React/RCTUIManager.h>
#import <React/RCTView.h>
#import <React/RCTViewManager.h>
@ -26,6 +28,8 @@
viewName:(NSString *)viewName
props:(NSDictionary *)props;
@property (nonatomic, copy, readonly) NSMutableDictionary<NSNumber *, RCTShadowView *> *shadowViewRegistry;
@end
@interface RCTPropsTestView : UIView
@ -74,6 +78,7 @@ RCT_CUSTOM_VIEW_PROPERTY(customProp, NSString, RCTPropsTestView)
@implementation RCTComponentPropsTests
{
RCTBridge *_bridge;
NSNumber *_rootViewReactTag;
}
- (void)setUp
@ -84,6 +89,16 @@ RCT_CUSTOM_VIEW_PROPERTY(customProp, NSString, RCTPropsTestView)
_bridge = [[RCTBridge alloc] initWithBundleURL:[bundle URLForResource:@"RNTesterUnitTestsBundle" withExtension:@"js"]
moduleProvider:nil
launchOptions:nil];
_rootViewReactTag = @1;
RCTUIManager *uiManager = _bridge.uiManager;
dispatch_async(uiManager.methodQueue, ^{
RCTRootShadowView *rootShadowView = [RCTRootShadowView new];
rootShadowView.reactTag = self->_rootViewReactTag;
uiManager.shadowViewRegistry[rootShadowView.reactTag] = rootShadowView;
});
RCT_RUN_RUNLOOP_WHILE(_bridge.isLoading);
}
@ -97,7 +112,7 @@ RCT_CUSTOM_VIEW_PROPERTY(customProp, NSString, RCTPropsTestView)
@"customProp": @"Goodbye"};
dispatch_async(uiManager.methodQueue, ^{
[uiManager createView:@2 viewName:@"RCTPropsTestView" rootTag:nil props:props];
[uiManager createView:@2 viewName:@"RCTPropsTestView" rootTag:self->_rootViewReactTag props:props];
[uiManager addUIBlock:^(__unused RCTUIManager *_uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
view = (RCTPropsTestView *)viewRegistry[@2];
XCTAssertEqual(view.integerProp, 58);
@ -126,7 +141,7 @@ RCT_CUSTOM_VIEW_PROPERTY(customProp, NSString, RCTPropsTestView)
@"customProp": [NSNull null]};
dispatch_async(uiManager.methodQueue, ^{
[uiManager createView:@2 viewName:@"RCTPropsTestView" rootTag:nil props:props];
[uiManager createView:@2 viewName:@"RCTPropsTestView" rootTag:self->_rootViewReactTag props:props];
[uiManager updateView:@2 viewName:@"RCTPropsTestView" props:resetProps];
[uiManager addUIBlock:^(__unused RCTUIManager *_uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
view = (RCTPropsTestView *)viewRegistry[@2];
@ -149,7 +164,7 @@ RCT_CUSTOM_VIEW_PROPERTY(customProp, NSString, RCTPropsTestView)
NSDictionary *resetProps = @{@"backgroundColor": [NSNull null]};
dispatch_async(uiManager.methodQueue, ^{
[uiManager createView:@2 viewName:@"RCTView" rootTag:nil props:props];
[uiManager createView:@2 viewName:@"RCTView" rootTag:self->_rootViewReactTag props:props];
[uiManager addUIBlock:^(__unused RCTUIManager *_uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
view = (RCTView *)viewRegistry[@2];
XCTAssertEqualObjects(view.backgroundColor, [RCTConvert UIColor:@0xffffffff]);

View File

@ -33,7 +33,7 @@
#import "RCTRootShadowView.h"
#import "RCTRootViewInternal.h"
#import "RCTScrollableProtocol.h"
#import "RCTShadowView+Hierarchy.h"
#import "RCTShadowView+Internal.h"
#import "RCTShadowView.h"
#import "RCTUIManagerObserverCoordinator.h"
#import "RCTUtils.h"
@ -939,7 +939,7 @@ RCT_EXPORT_METHOD(manageChildren:(nonnull NSNumber *)containerTag
RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
viewName:(NSString *)viewName
rootTag:(__unused NSNumber *)rootTag
rootTag:(nonnull NSNumber *)rootTag
props:(NSDictionary *)props)
{
RCTComponentData *componentData = _componentDataByName[viewName];
@ -952,6 +952,10 @@ RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTag
if (shadowView) {
[componentData setProps:props forShadowView:shadowView];
_shadowViewRegistry[reactTag] = shadowView;
RCTShadowView *rootView = _shadowViewRegistry[rootTag];
RCTAssert([rootView isKindOfClass:[RCTRootShadowView class]],
@"Given `rootTag` (%@) does not correspond to a valid root shadow view instance.", rootTag);
shadowView.rootView = (RCTRootShadowView *)rootView;
}
// Shadow view is the source of truth for background color this is a little

View File

@ -203,8 +203,6 @@
14F7A0F01BDA714B003C6C10 /* RCTFPSGraph.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F7A0EF1BDA714B003C6C10 /* RCTFPSGraph.m */; };
191E3EBE1C29D9AF00C180A6 /* RCTRefreshControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EBD1C29D9AF00C180A6 /* RCTRefreshControlManager.m */; };
191E3EC11C29DC3800C180A6 /* RCTRefreshControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */; };
19F0AD721F1DE7C400E4949F /* RCTShadowView+Hierarchy.h in Headers */ = {isa = PBXBuildFile; fileRef = 19F0AD701F1DE7C400E4949F /* RCTShadowView+Hierarchy.h */; };
19F0AD731F1DE7C400E4949F /* RCTShadowView+Hierarchy.m in Sources */ = {isa = PBXBuildFile; fileRef = 19F0AD711F1DE7C400E4949F /* RCTShadowView+Hierarchy.m */; };
19F61BFA1E8495CD00571D81 /* bignum-dtoa.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3A1E25C5A300323FB7 /* bignum-dtoa.h */; };
19F61BFB1E8495CD00571D81 /* bignum.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3C1E25C5A300323FB7 /* bignum.h */; };
19F61BFC1E8495CD00571D81 /* cached-powers.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 139D7E3E1E25C5A300323FB7 /* cached-powers.h */; };
@ -1013,6 +1011,10 @@
5960C1BE1F0804DF0066FD5B /* RCTLayoutAnimationGroup.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 5960C1B31F0804A00066FD5B /* RCTLayoutAnimationGroup.h */; };
5960C1BF1F0804F50066FD5B /* RCTLayoutAnimation.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 5960C1B11F0804A00066FD5B /* RCTLayoutAnimation.h */; };
5960C1C01F0804F50066FD5B /* RCTLayoutAnimationGroup.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 5960C1B31F0804A00066FD5B /* RCTLayoutAnimationGroup.h */; };
597633361F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */; };
597633371F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */; };
597633381F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; };
597633391F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */; };
59A7B9FD1E577DBF0068EDBF /* RCTRootContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A7B9FB1E577DBF0068EDBF /* RCTRootContentView.h */; };
59A7B9FE1E577DBF0068EDBF /* RCTRootContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A7B9FC1E577DBF0068EDBF /* RCTRootContentView.m */; };
59B1EBC91EBD46250047B19B /* RCTShadowView+Layout.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 590D7BFB1EBD458B00D8A370 /* RCTShadowView+Layout.h */; };
@ -1841,8 +1843,6 @@
191E3EBF1C29DC3800C180A6 /* RCTRefreshControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRefreshControl.h; sourceTree = "<group>"; };
191E3EC01C29DC3800C180A6 /* RCTRefreshControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRefreshControl.m; sourceTree = "<group>"; };
19DED2281E77E29200F089BB /* systemJSCWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = systemJSCWrapper.cpp; sourceTree = "<group>"; };
19F0AD701F1DE7C400E4949F /* RCTShadowView+Hierarchy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTShadowView+Hierarchy.h"; sourceTree = "<group>"; };
19F0AD711F1DE7C400E4949F /* RCTShadowView+Hierarchy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTShadowView+Hierarchy.m"; sourceTree = "<group>"; };
27B958731E57587D0096647A /* JSBigString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBigString.cpp; sourceTree = "<group>"; };
2D2A28131D9B038B00D4039D /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
352DCFEE1D19F4C20056D623 /* RCTI18nUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTI18nUtil.h; sourceTree = "<group>"; };
@ -1962,6 +1962,8 @@
5960C1B21F0804A00066FD5B /* RCTLayoutAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLayoutAnimation.m; sourceTree = "<group>"; };
5960C1B31F0804A00066FD5B /* RCTLayoutAnimationGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTLayoutAnimationGroup.h; sourceTree = "<group>"; };
5960C1B41F0804A00066FD5B /* RCTLayoutAnimationGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTLayoutAnimationGroup.m; sourceTree = "<group>"; };
597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTShadowView+Internal.m"; sourceTree = "<group>"; };
597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RCTShadowView+Internal.h"; sourceTree = "<group>"; };
59A7B9FB1E577DBF0068EDBF /* RCTRootContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTRootContentView.h; sourceTree = "<group>"; };
59A7B9FC1E577DBF0068EDBF /* RCTRootContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootContentView.m; sourceTree = "<group>"; };
59EB6DB91EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTUIManagerObserverCoordinator.h; sourceTree = "<group>"; };
@ -2329,8 +2331,8 @@
131B6AF31AF1093D00FFC3E0 /* RCTSegmentedControlManager.m */,
13E0674B1A70F44B002CDEE1 /* RCTShadowView.h */,
13E0674C1A70F44B002CDEE1 /* RCTShadowView.m */,
19F0AD701F1DE7C400E4949F /* RCTShadowView+Hierarchy.h */,
19F0AD711F1DE7C400E4949F /* RCTShadowView+Hierarchy.m */,
597633351F4E021D005BE8A4 /* RCTShadowView+Internal.h */,
597633341F4E021D005BE8A4 /* RCTShadowView+Internal.m */,
590D7BFB1EBD458B00D8A370 /* RCTShadowView+Layout.h */,
590D7BFC1EBD458B00D8A370 /* RCTShadowView+Layout.m */,
13AF20431AE707F8005F5298 /* RCTSlider.h */,
@ -2776,6 +2778,7 @@
3D302F371DF828F800D6DDAE /* RCTEventDispatcher.h in Headers */,
3D302F381DF828F800D6DDAE /* RCTFrameUpdate.h in Headers */,
3D302F391DF828F800D6DDAE /* RCTImageSource.h in Headers */,
597633391F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */,
3D302F3A1DF828F800D6DDAE /* RCTInvalidating.h in Headers */,
3D302F3B1DF828F800D6DDAE /* RCTJavaScriptExecutor.h in Headers */,
3D302F3C1DF828F800D6DDAE /* RCTJavaScriptLoader.h in Headers */,
@ -3049,6 +3052,7 @@
3D80DA271DF820620028D040 /* RCTConvert.h in Headers */,
3D80DA281DF820620028D040 /* RCTDefines.h in Headers */,
3D80DA291DF820620028D040 /* RCTDisplayLink.h in Headers */,
597633381F4E021D005BE8A4 /* RCTShadowView+Internal.h in Headers */,
3D80DA2A1DF820620028D040 /* RCTErrorCustomizer.h in Headers */,
3D80DA2B1DF820620028D040 /* RCTErrorInfo.h in Headers */,
1384E2081E806D4E00545659 /* RCTNativeModule.h in Headers */,
@ -3152,7 +3156,6 @@
657734901EE8354A00A0E9EA /* RCTInspectorPackagerConnection.h in Headers */,
3D7BFD1D1EA8E351008DFB7A /* RCTPackagerConnection.h in Headers */,
3D80DA7F1DF820620028D040 /* RCTScrollView.h in Headers */,
19F0AD721F1DE7C400E4949F /* RCTShadowView+Hierarchy.h in Headers */,
3D80DA801DF820620028D040 /* RCTScrollViewManager.h in Headers */,
3D80DA811DF820620028D040 /* RCTSegmentedControl.h in Headers */,
C6827DF61EF17CCC00D66BEF /* RCTJSEnvironment.h in Headers */,
@ -3659,6 +3662,7 @@
2D3B5EA51D9B08C700451313 /* RCTRootView.m in Sources */,
13134C871E296B2A00B9F3CB /* RCTCxxBridge.mm in Sources */,
CF2731C31E7B8DF30044CA4F /* RCTDeviceInfo.m in Sources */,
597633371F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */,
2D3B5EB11D9B090100451313 /* RCTAppState.m in Sources */,
1384E20B1E806D5B00545659 /* RCTNativeModule.mm in Sources */,
2D3B5EC21D9B093B00451313 /* RCTProfile.m in Sources */,
@ -3855,6 +3859,7 @@
buildActionMask = 2147483647;
files = (
13134C9A1E296B2A00B9F3CB /* RCTCxxMethod.mm in Sources */,
597633361F4E021D005BE8A4 /* RCTShadowView+Internal.m in Sources */,
59FBEFB61E46D91C0095D885 /* RCTScrollContentViewManager.m in Sources */,
13723B501A82FD3C00F88898 /* RCTStatusBarManager.m in Sources */,
000E6CEB1AB0E980000CDF4D /* RCTSourceCode.m in Sources */,
@ -3914,7 +3919,6 @@
13B080261A694A8400A75B9A /* RCTWrapperViewController.m in Sources */,
13B080051A6947C200A75B9A /* RCTScrollView.m in Sources */,
A2440AA31DF8D854006E7BFC /* RCTReloadCommand.m in Sources */,
19F0AD731F1DE7C400E4949F /* RCTShadowView+Hierarchy.m in Sources */,
3DF1BE821F26576400068F1A /* JSCTracing.cpp in Sources */,
6577348F1EE8354A00A0E9EA /* RCTInspector.mm in Sources */,
E9B20B7B1B500126007A2DA7 /* RCTAccessibilityManager.m in Sources */,

View File

@ -6,11 +6,15 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <React/RCTRootShadowView.h>
#import <UIKit/UIKit.h>
#import <React/RCTShadowView.h>
@interface RCTShadowView (Hierarchy)
@class RCTRootShadowView;
@property (nonatomic, readonly) RCTRootShadowView *rootView;
@interface RCTShadowView (Internal)
@property (nonatomic, weak, readwrite) RCTRootShadowView *rootView;
@end

View File

@ -6,18 +6,21 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "RCTShadowView+Hierarchy.h"
@implementation RCTShadowView (Hierarchy)
#import "RCTShadowView+Layout.h"
- (nullable RCTRootShadowView *)rootView
@interface RCTShadowView ()
{
RCTShadowView *view = self;
while (view != nil && ![view isKindOfClass:[RCTRootShadowView class]]) {
view = view.superview;
}
return (RCTRootShadowView *)view;
__weak RCTRootShadowView *_rootView;
}
@end
@implementation RCTShadowView (Internal)
- (void)setRootView:(RCTRootShadowView *)rootView
{
_rootView = rootView;
}
@end

View File

@ -13,6 +13,7 @@
#import <React/RCTRootView.h>
#import <yoga/Yoga.h>
@class RCTRootShadowView;
@class RCTSparseArray;
typedef NS_ENUM(NSUInteger, RCTUpdateLifecycle) {
@ -50,6 +51,7 @@ typedef void (^RCTApplierBlock)(NSDictionary<NSNumber *, UIView *> *viewRegistry
- (void)insertReactSubview:(RCTShadowView *)subview atIndex:(NSInteger)atIndex NS_REQUIRES_SUPER;
- (void)removeReactSubview:(RCTShadowView *)subview NS_REQUIRES_SUPER;
@property (nonatomic, weak, readonly) RCTRootShadowView *rootView;
@property (nonatomic, weak, readonly) RCTShadowView *superview;
@property (nonatomic, assign, readonly) YGNodeRef yogaNode;
@property (nonatomic, copy) NSString *viewName;