Skip to content

Commit

Permalink
RCTShadowView have got rootView property
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shergin authored and facebook-github-bot committed Aug 24, 2017
1 parent e6ff0da commit 6493a85
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 24 deletions.
21 changes: 18 additions & 3 deletions RNTester/RNTesterUnitTests/RCTComponentPropsTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -26,6 +28,8 @@ - (void)updateView:(nonnull NSNumber *)reactTag
viewName:(NSString *)viewName
props:(NSDictionary *)props;

@property (nonatomic, copy, readonly) NSMutableDictionary<NSNumber *, RCTShadowView *> *shadowViewRegistry;

@end

@interface RCTPropsTestView : UIView
Expand Down Expand Up @@ -74,6 +78,7 @@ @interface RCTComponentPropsTests : XCTestCase
@implementation RCTComponentPropsTests
{
RCTBridge *_bridge;
NSNumber *_rootViewReactTag;
}

- (void)setUp
Expand All @@ -84,6 +89,16 @@ - (void)setUp
_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);
}

Expand All @@ -97,7 +112,7 @@ - (void)testSetProps
@"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);
Expand Down Expand Up @@ -126,7 +141,7 @@ - (void)testResetProps
@"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];
Expand All @@ -149,7 +164,7 @@ - (void)testResetBackgroundColor
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]);
Expand Down
8 changes: 6 additions & 2 deletions React/Modules/RCTUIManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -939,7 +939,7 @@ - (void)_manageChildren:(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];
Expand All @@ -952,6 +952,10 @@ - (void)_manageChildren:(NSNumber *)containerTag
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
Expand Down
20 changes: 12 additions & 8 deletions React/React.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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 */; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -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>"; };
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down Expand Up @@ -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 */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

@interface RCTShadowView (Internal)

@property (nonatomic, readonly) RCTRootShadowView *rootView;
@property (nonatomic, weak, readwrite) RCTRootShadowView *rootView;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
__weak RCTRootShadowView *_rootView;
}

@end

return (RCTRootShadowView *)view;
@implementation RCTShadowView (Internal)

- (void)setRootView:(RCTRootShadowView *)rootView
{
_rootView = rootView;
}

@end
2 changes: 2 additions & 0 deletions React/Views/RCTShadowView.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#import <React/RCTRootView.h>
#import <yoga/Yoga.h>

@class RCTRootShadowView;
@class RCTSparseArray;

typedef NS_ENUM(NSUInteger, RCTUpdateLifecycle) {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 6493a85

Please sign in to comment.