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
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ActivityIndicatorViewProps>();
_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<ActivityIndicatorViewProps>();
}
_props = props;
const auto &oldViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(oldProps ?: _props);
const auto &newViewProps = *std::static_pointer_cast<const ActivityIndicatorViewProps>(props);
[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 (newViewProps.animating) {
[_activityIndicatorView startAnimating];

View File

@ -27,11 +27,13 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ImageProps>();
_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<const ImageProps>();
}
_props = props;
const auto &oldImageProps = *std::static_pointer_cast<const ImageProps>(oldProps ?: _props);
const auto &newImageProps = *std::static_pointer_cast<const ImageProps>(props);
[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`
if (oldImageProps.resizeMode != newImageProps.resizeMode) {
if (newImageProps.resizeMode == ImageResizeMode::Repeat) {

View File

@ -7,6 +7,20 @@
#import "RCTRootComponentView.h"
#import <fabric/components/root/RootProps.h>
using namespace facebook::react;
@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

View File

@ -33,6 +33,9 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ScrollViewProps>();
_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<const ScrollViewProps>(oldProps ?: _props);
const auto &newScrollViewProps = *std::static_pointer_cast<const ScrollViewProps>(props);
[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) \
if (oldScrollViewProps.reactName != newScrollViewProps.reactName) { \
target.localName = newScrollViewProps.reactName; \

View File

@ -20,15 +20,16 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const SwitchProps>();
_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<SwitchProps>();
}
_props = props;
const auto &oldSwitchProps = *std::static_pointer_cast<const SwitchProps>(oldProps ?: _props);
const auto &newSwitchProps = *std::static_pointer_cast<const SwitchProps>(props);
[super updateProps:props oldProps:oldProps];
auto oldSwitchProps = *std::dynamic_pointer_cast<const SwitchProps>(oldProps);
auto newSwitchProps = *std::dynamic_pointer_cast<const SwitchProps>(props);
// `value`
if (oldSwitchProps.value != newSwitchProps.value) {
_switchView.on = newSwitchProps.value;

View File

@ -25,6 +25,9 @@ using namespace facebook::react;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const ParagraphProps>();
_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 &paragraphProps = std::static_pointer_cast<const ParagraphProps>(props);
[super updateProps:props oldProps:oldProps];
auto paragraphProps = std::static_pointer_cast<const ParagraphProps>(props);
assert(paragraphProps);
_paragraphAttributes = paragraphProps->paragraphAttributes;
}

View File

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

View File

@ -10,6 +10,7 @@
#import <fabric/components/view/ViewProps.h>
#import <fabric/components/view/ViewEventEmitter.h>
#import <objc/runtime.h>
#import <React/RCTAssert.h>
#import <React/RCTBorderDrawing.h>
#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<const ViewProps>();
_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<ViewProps>();
}
_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<const ViewProps>(oldProps);
auto newViewProps = *std::dynamic_pointer_cast<const ViewProps>(props);
const auto &oldViewProps = *std::static_pointer_cast<const ViewProps>(oldProps ?: _props);
const auto &newViewProps = *std::static_pointer_cast<const ViewProps>(props);
_props = std::static_pointer_cast<const ViewProps>(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<const ViewProps>(_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<const ViewProps>(_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<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;
}
NSMutableArray<UIAccessibilityCustomAction *> *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:)]];