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
This commit is contained in:
Valentin Shergin 2018-09-10 16:33:46 -07:00 committed by Facebook Github Bot
parent 5d55f0368e
commit 37d19aaae3
8 changed files with 83 additions and 58 deletions

View File

@ -27,19 +27,20 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ActivityIndicatorViewProps>();
_props = defaultProps;
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds]; _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:self.bounds];
_activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _activityIndicatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
const auto &defaultProps = ActivityIndicatorViewProps(); if (defaultProps->animating) {
if (defaultProps.animating) {
[_activityIndicatorView startAnimating]; [_activityIndicatorView startAnimating];
} else { } else {
[_activityIndicatorView stopAnimating]; [_activityIndicatorView stopAnimating];
} }
_activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps.color.get()]; _activityIndicatorView.color = [UIColor colorWithCGColor:defaultProps->color.get()];
_activityIndicatorView.hidesWhenStopped = defaultProps.hidesWhenStopped; _activityIndicatorView.hidesWhenStopped = defaultProps->hidesWhenStopped;
_activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps.size); _activityIndicatorView.activityIndicatorViewStyle = convertActivityIndicatorViewStyle(defaultProps->size);
[self addSubview:_activityIndicatorView]; [self addSubview:_activityIndicatorView];
} }
@ -49,16 +50,11 @@ static UIActivityIndicatorViewStyle convertActivityIndicatorViewStyle(const Acti
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{ {
if (!oldProps) { const auto &oldViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(oldProps ?: _props);
oldProps = _props ?: std::make_shared<ActivityIndicatorViewProps>(); const auto &newViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(props);
}
_props = props;
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
auto oldViewProps = *std::dynamic_pointer_cast<const ActivityIndicatorViewProps>(oldProps);
auto newViewProps = *std::dynamic_pointer_cast<const ActivityIndicatorViewProps>(props);
if (oldViewProps.animating != newViewProps.animating) { if (oldViewProps.animating != newViewProps.animating) {
if (newViewProps.animating) { if (newViewProps.animating) {
[_activityIndicatorView startAnimating]; [_activityIndicatorView startAnimating];

View File

@ -27,11 +27,13 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ImageProps>();
_props = defaultProps;
_imageView = [[UIImageView alloc] initWithFrame:self.bounds]; _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
_imageView.clipsToBounds = YES; _imageView.clipsToBounds = YES;
auto defaultProps = ImageProps(); _imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps->resizeMode);
_imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps.resizeMode);
self.contentView = _imageView; self.contentView = _imageView;
} }
@ -43,16 +45,11 @@ using namespace facebook::react;
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{ {
if (!oldProps) { const auto &oldImageProps = *std::static_pointer_cast<const ImageProps>(oldProps ?: _props);
oldProps = _props ?: std::make_shared<const ImageProps>(); const auto &newImageProps = *std::static_pointer_cast<const ImageProps>(props);
}
_props = props;
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
const auto &oldImageProps = *std::dynamic_pointer_cast<const ImageProps>(oldProps);
const auto &newImageProps = *std::dynamic_pointer_cast<const ImageProps>(props);
// `resizeMode` // `resizeMode`
if (oldImageProps.resizeMode != newImageProps.resizeMode) { if (oldImageProps.resizeMode != newImageProps.resizeMode) {
if (newImageProps.resizeMode == ImageResizeMode::Repeat) { if (newImageProps.resizeMode == ImageResizeMode::Repeat) {

View File

@ -7,6 +7,20 @@
#import "RCTRootComponentView.h" #import "RCTRootComponentView.h"
#import <fabric/components/root/RootProps.h>
using namespace facebook::react;
@implementation RCTRootComponentView @implementation RCTRootComponentView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RootProps>();
_props = defaultProps;
}
return self;
}
@end @end

View File

@ -33,6 +33,9 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ScrollViewProps>();
_props = defaultProps;
_scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds]; _scrollView = [[RCTEnhancedScrollView alloc] initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delegate = self; _scrollView.delegate = self;
@ -49,16 +52,11 @@ using namespace facebook::react;
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{ {
const auto &oldScrollViewProps = *std::static_pointer_cast<const ScrollViewProps>(oldProps ?: _props);
const auto &newScrollViewProps = *std::static_pointer_cast<const ScrollViewProps>(props);
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
if (!oldProps) {
oldProps = _props ?: std::make_shared<ScrollViewProps>();
}
_props = props;
auto oldScrollViewProps = *std::dynamic_pointer_cast<const ScrollViewProps>(oldProps);
auto newScrollViewProps = *std::dynamic_pointer_cast<const ScrollViewProps>(props);
#define REMAP_PROP(reactName, localName, target) \ #define REMAP_PROP(reactName, localName, target) \
if (oldScrollViewProps.reactName != newScrollViewProps.reactName) { \ if (oldScrollViewProps.reactName != newScrollViewProps.reactName) { \
target.localName = newScrollViewProps.reactName; \ target.localName = newScrollViewProps.reactName; \

View File

@ -20,15 +20,16 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const SwitchProps>();
_props = defaultProps;
_switchView = [[UISwitch alloc] initWithFrame:self.bounds]; _switchView = [[UISwitch alloc] initWithFrame:self.bounds];
[_switchView addTarget:self [_switchView addTarget:self
action:@selector(onChange:) action:@selector(onChange:)
forControlEvents:UIControlEventValueChanged]; forControlEvents:UIControlEventValueChanged];
const auto &defaultProps = SwitchProps(); _switchView.on = defaultProps->value;
_switchView.on = defaultProps.value;
self.contentView = _switchView; self.contentView = _switchView;
} }
@ -38,16 +39,11 @@ using namespace facebook::react;
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{ {
if (!oldProps) { const auto &oldSwitchProps = *std::static_pointer_cast<const SwitchProps>(oldProps ?: _props);
oldProps = _props ?: std::make_shared<SwitchProps>(); const auto &newSwitchProps = *std::static_pointer_cast<const SwitchProps>(props);
}
_props = props;
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
auto oldSwitchProps = *std::dynamic_pointer_cast<const SwitchProps>(oldProps);
auto newSwitchProps = *std::dynamic_pointer_cast<const SwitchProps>(props);
// `value` // `value`
if (oldSwitchProps.value != newSwitchProps.value) { if (oldSwitchProps.value != newSwitchProps.value) {
_switchView.on = newSwitchProps.value; _switchView.on = newSwitchProps.value;

View File

@ -25,6 +25,9 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
{ {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ParagraphProps>();
_props = defaultProps;
self.isAccessibilityElement = YES; self.isAccessibilityElement = YES;
self.accessibilityTraits |= UIAccessibilityTraitStaticText; self.accessibilityTraits |= UIAccessibilityTraitStaticText;
self.opaque = NO; self.opaque = NO;
@ -36,8 +39,10 @@ using namespace facebook::react;
- (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps - (void)updateProps:(SharedProps)props oldProps:(SharedProps)oldProps
{ {
const auto &paragraphProps = std::static_pointer_cast<const ParagraphProps>(props);
[super updateProps:props oldProps:oldProps]; [super updateProps:props oldProps:oldProps];
auto paragraphProps = std::static_pointer_cast<const ParagraphProps>(props);
assert(paragraphProps); assert(paragraphProps);
_paragraphAttributes = paragraphProps->paragraphAttributes; _paragraphAttributes = paragraphProps->paragraphAttributes;
} }

View File

@ -12,6 +12,7 @@
#import <fabric/core/LayoutMetrics.h> #import <fabric/core/LayoutMetrics.h>
#import <fabric/core/Props.h> #import <fabric/core/Props.h>
#import <fabric/components/view/ViewEventEmitter.h> #import <fabric/components/view/ViewEventEmitter.h>
#import <fabric/components/view/ViewProps.h>
#import <fabric/events/EventEmitter.h> #import <fabric/events/EventEmitter.h>
#import <React/RCTTouchableComponentViewProtocol.h> #import <React/RCTTouchableComponentViewProtocol.h>
@ -23,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface RCTViewComponentView : UIView <RCTComponentViewProtocol, RCTTouchableComponentViewProtocol> { @interface RCTViewComponentView : UIView <RCTComponentViewProtocol, RCTTouchableComponentViewProtocol> {
@protected @protected
facebook::react::LayoutMetrics _layoutMetrics; facebook::react::LayoutMetrics _layoutMetrics;
facebook::react::SharedProps _props; facebook::react::SharedViewProps _props;
facebook::react::SharedViewEventEmitter _eventEmitter; facebook::react::SharedViewEventEmitter _eventEmitter;
} }

View File

@ -10,6 +10,7 @@
#import <fabric/components/view/ViewProps.h> #import <fabric/components/view/ViewProps.h>
#import <fabric/components/view/ViewEventEmitter.h> #import <fabric/components/view/ViewEventEmitter.h>
#import <objc/runtime.h> #import <objc/runtime.h>
#import <React/RCTAssert.h>
#import <React/RCTBorderDrawing.h> #import <React/RCTBorderDrawing.h>
#import "RCTConversions.h" #import "RCTConversions.h"
@ -21,6 +22,16 @@ using namespace facebook::react;
UIColor *_backgroundColor; UIColor *_backgroundColor;
} }
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ViewProps>();
_props = defaultProps;
}
return self;
}
- (void)setContentView:(UIView *)contentView - (void)setContentView:(UIView *)contentView
{ {
if (_contentView) { if (_contentView) {
@ -65,13 +76,23 @@ using namespace facebook::react;
- (void)updateProps:(SharedProps)props - (void)updateProps:(SharedProps)props
oldProps:(SharedProps)oldProps oldProps:(SharedProps)oldProps
{ {
if (!oldProps) { #ifndef NS_BLOCK_ASSERTIONS
oldProps = _props ?: std::make_shared<ViewProps>(); auto propsRawPtr = _props.get();
} RCTAssert(
_props = props; 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<const ViewProps>(oldProps); const auto &oldViewProps = *std::static_pointer_cast<const ViewProps>(oldProps ?: _props);
auto newViewProps = *std::dynamic_pointer_cast<const ViewProps>(props); const auto &newViewProps = *std::static_pointer_cast<const ViewProps>(props);
_props = std::static_pointer_cast<const ViewProps>(props);
BOOL needsInvalidateLayer = NO; BOOL needsInvalidateLayer = NO;
@ -232,8 +253,7 @@ using namespace facebook::react;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{ {
auto viewProps = *std::static_pointer_cast<const ViewProps>(_props); switch (_props->pointerEvents) {
switch (viewProps.pointerEvents) {
case PointerEventsMode::Auto: case PointerEventsMode::Auto:
return [self betterHitTest:point withEvent:event]; return [self betterHitTest:point withEvent:event];
case PointerEventsMode::None: case PointerEventsMode::None:
@ -286,10 +306,8 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
- (void)invalidateLayer - (void)invalidateLayer
{ {
const auto &props = *std::dynamic_pointer_cast<const ViewProps>(_props);
const auto borderMetrics = const auto borderMetrics =
props.resolveBorderMetrics(_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft); _props->resolveBorderMetrics(_layoutMetrics.layoutDirection == LayoutDirection::RightToLeft);
CALayer *layer = self.layer; CALayer *layer = self.layer;
@ -415,14 +433,14 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) {
- (NSArray<UIAccessibilityCustomAction *> *)accessibilityCustomActions - (NSArray<UIAccessibilityCustomAction *> *)accessibilityCustomActions
{ {
const auto &accessibilityProps = *std::dynamic_pointer_cast<const AccessibilityProps>(_props); const auto &accessibilityActions = _props->accessibilityActions;
if (accessibilityProps.accessibilityActions.size() == 0) { if (accessibilityActions.size() == 0) {
return nil; return nil;
} }
NSMutableArray<UIAccessibilityCustomAction *> *customActions = [NSMutableArray array]; NSMutableArray<UIAccessibilityCustomAction *> *customActions = [NSMutableArray array];
for (const auto &accessibilityAction : accessibilityProps.accessibilityActions) { for (const auto &accessibilityAction : accessibilityActions) {
[customActions addObject:[[UIAccessibilityCustomAction alloc] initWithName:RCTNSStringFromString(accessibilityAction) [customActions addObject:[[UIAccessibilityCustomAction alloc] initWithName:RCTNSStringFromString(accessibilityAction)
target:self target:self
selector:@selector(didActivateAccessibilityCustomAction:)]]; selector:@selector(didActivateAccessibilityCustomAction:)]];