From 37d19aaae391d95e973cbc3ecef88f01f60cdeb7 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 10 Sep 2018 16:33:46 -0700 Subject: [PATCH] Fabric: Unification of props management in RCTViewComponentView and subclasses Summary: * Now all `RCTViewComponentView` subclasses are required to set `_props` instance variable in the constructor with a default value; * `RCTViewComponentView`'s `_props` instance variable now has `ShadredViewProps` type (that enforced by `static_assert` in `ConcreteViewShadowNode` template); * New we use `static_pointer_cast` instead of `dynamic_pointer_cast` for casting props. Reviewed By: mdvacca Differential Revision: D9734199 fbshipit-source-id: b0a0939c936f8b5b540fa5fa1e4a2f1037346fc5 --- .../RCTActivityIndicatorViewComponentView.mm | 22 ++++----- .../Image/RCTImageComponentView.mm | 15 +++--- .../Root/RCTRootComponentView.mm | 14 ++++++ .../ScrollView/RCTScrollViewComponentView.mm | 14 +++--- .../Switch/RCTSwitchComponentView.mm | 20 ++++---- .../Text/RCTParagraphComponentView.mm | 7 ++- .../View/RCTViewComponentView.h | 3 +- .../View/RCTViewComponentView.mm | 46 +++++++++++++------ 8 files changed, 83 insertions(+), 58 deletions(-) diff --git a/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm index 2e883cb0c..c9eafe38a 100644 --- a/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ActivityIndicator/RCTActivityIndicatorViewComponentView.mm @@ -27,19 +27,20 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds]; _activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - const auto &defaultProps = ActivityIndicatorViewProps(); - - if (defaultProps.animating) { + if (defaultProps->animating) { [_activityIndicatorView startAnimating]; } else { [_activityIndicatorView stopAnimating]; } - _activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps.color.get()]; - _activityIndicatorView.hidesWhenStopped = defaultProps.hidesWhenStopped; - _activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps.size); + _activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps->color.get()]; + _activityIndicatorView.hidesWhenStopped = defaultProps->hidesWhenStopped; + _activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps->size); [self addSubview:_activityIndicatorView]; } @@ -49,16 +50,11 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { - if (!oldProps) { - oldProps = _props ?: std::make_shared(); - } - _props = props; + const auto &oldViewProps = *std::static_pointer_cast(oldProps ?: _props); + const auto &newViewProps = *std::static_pointer_cast(props); [super updateProps:props oldProps:oldProps]; - auto oldViewProps = *std::dynamic_pointer_cast(oldProps); - auto newViewProps = *std::dynamic_pointer_cast(props); - if (oldViewProps.animating != newViewProps.animating) { if (newViewProps.animating) { [_activityIndicatorView startAnimating]; diff --git a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm index cb8dcd7fc..4bd3c8a12 100644 --- a/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm @@ -27,11 +27,13 @@ using namespace facebook::react; - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView.clipsToBounds = YES; - auto defaultProps = ImageProps(); - _imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps.resizeMode); + _imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps->resizeMode); self.contentView = _imageView; } @@ -43,16 +45,11 @@ using namespace facebook::react; - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { - if (!oldProps) { - oldProps = _props ?: std::make_shared(); - } - _props = props; + const auto &oldImageProps = *std::static_pointer_cast(oldProps ?: _props); + const auto &newImageProps = *std::static_pointer_cast(props); [super updateProps:props oldProps:oldProps]; - const auto &oldImageProps = *std::dynamic_pointer_cast(oldProps); - const auto &newImageProps = *std::dynamic_pointer_cast(props); - // `resizeMode` if (oldImageProps.resizeMode != newImageProps.resizeMode) { if (newImageProps.resizeMode == ImageResizeMode::Repeat) { diff --git a/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm b/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm index 703c03e5d..a75041b8c 100644 --- a/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Root/RCTRootComponentView.mm @@ -7,6 +7,20 @@ #import "RCTRootComponentView.h" +#import + +using namespace facebook::react; + @implementation RCTRootComponentView +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + } + + return self; +} + @end diff --git a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 018f45b83..5c15d7151 100644 --- a/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -33,6 +33,9 @@ using namespace facebook::react; - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds]; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _scrollView.delegate = self; @@ -49,16 +52,11 @@ using namespace facebook::react; - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { + const auto &oldScrollViewProps = *std::static_pointer_cast(oldProps ?: _props); + const auto &newScrollViewProps = *std::static_pointer_cast(props); + [super updateProps:props oldProps:oldProps]; - if (!oldProps) { - oldProps = _props ?: std::make_shared(); - } - _props = props; - - auto oldScrollViewProps = *std::dynamic_pointer_cast(oldProps); - auto newScrollViewProps = *std::dynamic_pointer_cast(props); - #define REMAP_PROP(reactName, localName, target) \ if (oldScrollViewProps.reactName != newScrollViewProps.reactName) { \ target.localName = newScrollViewProps.reactName; \ diff --git a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm index f58ac227c..c859c9a5e 100644 --- a/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm @@ -20,15 +20,16 @@ using namespace facebook::react; - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + _switchView = [[UISwitch alloc] initWithFrame:self.bounds]; [_switchView addTarget:self - action:@selector(onChange:) - forControlEvents:UIControlEventValueChanged]; + action:@selector(onChange:) + forControlEvents:UIControlEventValueChanged]; - const auto &defaultProps = SwitchProps(); - - _switchView.on = defaultProps.value; + _switchView.on = defaultProps->value; self.contentView = _switchView; } @@ -38,16 +39,11 @@ using namespace facebook::react; - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { - if (!oldProps) { - oldProps = _props ?: std::make_shared(); - } - _props = props; + const auto &oldSwitchProps = *std::static_pointer_cast(oldProps ?: _props); + const auto &newSwitchProps = *std::static_pointer_cast(props); [super updateProps:props oldProps:oldProps]; - auto oldSwitchProps = *std::dynamic_pointer_cast(oldProps); - auto newSwitchProps = *std::dynamic_pointer_cast(props); - // `value` if (oldSwitchProps.value != newSwitchProps.value) { _switchView.on = newSwitchProps.value; diff --git a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index bd0b5d914..724e26e05 100644 --- a/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -25,6 +25,9 @@ using namespace facebook::react; - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + self.isAccessibilityElement = YES; self.accessibilityTraits |= UIAccessibilityTraitStaticText; self.opaque = NO; @@ -36,8 +39,10 @@ using namespace facebook::react; - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { + const auto ¶graphProps = std::static_pointer_cast(props); + [super updateProps:props oldProps:oldProps]; - auto paragraphProps = std::static_pointer_cast(props); + assert(paragraphProps); _paragraphAttributes = paragraphProps->paragraphAttributes; } diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index d966bb7a4..5663db333 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -12,6 +12,7 @@ #import #import #import +#import #import #import @@ -23,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN @interface RCTViewComponentView : UIView { @protected facebook::react::LayoutMetrics _layoutMetrics; - facebook::react::SharedProps _props; + facebook::react::SharedViewProps _props; facebook::react::SharedViewEventEmitter _eventEmitter; } diff --git a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 870f41d9a..c648920b3 100644 --- a/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -10,6 +10,7 @@ #import #import #import +#import #import #import "RCTConversions.h" @@ -21,6 +22,16 @@ using namespace facebook::react; UIColor *_backgroundColor; } +- (instancetype)initWithFrame:(CGRect)frame +{ + if (self = [super initWithFrame:frame]) { + static const auto defaultProps = std::make_shared(); + _props = defaultProps; + } + + return self; +} + - (void)setContentView:(UIView *)contentView { if (_contentView) { @@ -65,13 +76,23 @@ using namespace facebook::react; - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps { - if (!oldProps) { - oldProps = _props ?: std::make_shared(); - } - _props = props; +#ifndef NS_BLOCK_ASSERTIONS + auto propsRawPtr = _props.get(); + RCTAssert( + propsRawPtr && + ( + [self class] == [RCTViewComponentView class] || + typeid(*propsRawPtr).hash_code() != typeid(const ViewProps).hash_code() + ), + @"`RCTViewComponentView` subclasses (and `%@` particularly) must setup `_props`" + " instance variable with a default value in the constructor.", NSStringFromClass([self class]) + ); +#endif - auto oldViewProps = *std::dynamic_pointer_cast(oldProps); - auto newViewProps = *std::dynamic_pointer_cast(props); + const auto &oldViewProps = *std::static_pointer_cast(oldProps ?: _props); + const auto &newViewProps = *std::static_pointer_cast(props); + + _props = std::static_pointer_cast(props); BOOL needsInvalidateLayer = NO; @@ -232,8 +253,7 @@ using namespace facebook::react; - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { - auto viewProps = *std::static_pointer_cast(_props); - switch (viewProps.pointerEvents) { + switch (_props->pointerEvents) { case PointerEventsMode::Auto: return [self betterHitTest:point withEvent:event]; case PointerEventsMode::None: @@ -286,10 +306,8 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) { - (void)invalidateLayer { - const auto &props = *std::dynamic_pointer_cast(_props); - const auto borderMetrics = - props.resolveBorderMetrics(_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft); + _props->resolveBorderMetrics(_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft); CALayer *layer = self.layer; @@ -415,14 +433,14 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) { - (NSArray *)accessibilityCustomActions { - const auto &accessibilityProps = *std::dynamic_pointer_cast(_props); + const auto &accessibilityActions = _props->accessibilityActions; - if (accessibilityProps.accessibilityActions.size() == 0) { + if (accessibilityActions.size() == 0) { return nil; } NSMutableArray *customActions = [NSMutableArray array]; - for (const auto &accessibilityAction : accessibilityProps.accessibilityActions) { + for (const auto &accessibilityAction : accessibilityActions) { [customActions addObject:[[UIAccessibilityCustomAction alloc] initWithName:RCTNSStringFromString(accessibilityAction) target:self selector:@selector(didActivateAccessibilityCustomAction:)]];