mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-26 05:15:49 +08:00
Refactor RCTUIManager
Summary: Moved the view creation & property binding logic out of RCTUIManager into a separate RCTComponentData class - this follows the pattern used with the bridge. I've also updated the property binding to use pre-allocated blocks for setting the values, which is more efficient than the previous system that re-contructed the selectors each time it was called. This should improve view update performance significantly.
This commit is contained in:
@@ -7,19 +7,21 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
/**
|
||||
* Logical node in a tree of application components. Both `ShadowView`s and
|
||||
* `UIView+React`s conform to this. Allows us to write utilities that
|
||||
* reason about trees generally.
|
||||
* Logical node in a tree of application components. Both `ShadowView` and
|
||||
* `UIView` conforms to this. Allows us to write utilities that reason about
|
||||
* trees generally.
|
||||
*/
|
||||
@protocol RCTViewNodeProtocol <NSObject>
|
||||
@protocol RCTComponent <NSObject>
|
||||
|
||||
@property (nonatomic, copy) NSNumber *reactTag;
|
||||
|
||||
- (void)insertReactSubview:(id<RCTViewNodeProtocol>)subview atIndex:(NSInteger)atIndex;
|
||||
- (void)removeReactSubview:(id<RCTViewNodeProtocol>)subview;
|
||||
- (void)insertReactSubview:(id<RCTComponent>)subview atIndex:(NSInteger)atIndex;
|
||||
- (void)removeReactSubview:(id<RCTComponent>)subview;
|
||||
- (NSArray *)reactSubviews;
|
||||
- (id<RCTViewNodeProtocol>)reactSuperview;
|
||||
- (id<RCTComponent>)reactSuperview;
|
||||
- (NSNumber *)reactTagAtPoint:(CGPoint)point;
|
||||
|
||||
// View/ShadowView is a root view
|
||||
32
React/Views/RCTComponentData.h
Normal file
32
React/Views/RCTComponentData.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTComponent.h"
|
||||
#import "RCTDefines.h"
|
||||
|
||||
@class RCTShadowView;
|
||||
@class RCTViewManager;
|
||||
|
||||
@interface RCTComponentData : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *name;
|
||||
@property (nonatomic, strong, readonly) RCTViewManager *manager;
|
||||
|
||||
- (instancetype)initWithManager:(RCTViewManager *)manager NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (id<RCTComponent>)createViewWithTag:(NSNumber *)tag;
|
||||
- (RCTShadowView *)createShadowViewWithTag:(NSNumber *)tag;
|
||||
- (void)setProps:(NSDictionary *)props forView:(id<RCTComponent>)view;
|
||||
- (void)setProps:(NSDictionary *)props forShadowView:(RCTShadowView *)shadowView;
|
||||
|
||||
- (NSDictionary *)viewConfig;
|
||||
|
||||
@end
|
||||
321
React/Views/RCTComponentData.m
Normal file
321
React/Views/RCTComponentData.m
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* 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 "RCTComponentData.h"
|
||||
|
||||
#import <objc/message.h>
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTShadowView.h"
|
||||
#import "RCTViewManager.h"
|
||||
|
||||
typedef void (^RCTPropBlock)(id<RCTComponent> view, id json);
|
||||
|
||||
@interface RCTComponentProp : NSObject
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *type;
|
||||
@property (nonatomic, copy) RCTPropBlock propBlock;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTComponentProp
|
||||
|
||||
- (instancetype)initWithType:(NSString *)type
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_type = [type copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTComponentData
|
||||
{
|
||||
id<RCTComponent> _defaultView;
|
||||
RCTShadowView *_defaultShadowView;
|
||||
NSMutableDictionary *_viewPropBlocks;
|
||||
NSMutableDictionary *_shadowPropBlocks;
|
||||
}
|
||||
|
||||
- (instancetype)initWithManager:(RCTViewManager *)manager
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_manager = manager;
|
||||
_viewPropBlocks = [[NSMutableDictionary alloc] init];
|
||||
_shadowPropBlocks = [[NSMutableDictionary alloc] init];
|
||||
|
||||
_name = RCTBridgeModuleNameForClass([manager class]);
|
||||
RCTAssert(_name.length, @"Invalid moduleName '%@'", _name);
|
||||
if ([_name hasSuffix:@"Manager"]) {
|
||||
_name = [_name substringToIndex:_name.length - @"Manager".length];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-init)
|
||||
|
||||
- (id<RCTComponent>)createViewWithTag:(NSNumber *)tag
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
id<RCTComponent> view = (id<RCTComponent>)[_manager view];
|
||||
view.reactTag = tag;
|
||||
if ([view isKindOfClass:[UIView class]]) {
|
||||
((UIView *)view).multipleTouchEnabled = YES;
|
||||
((UIView *)view).userInteractionEnabled = YES; // required for touch handling
|
||||
((UIView *)view).layer.allowsGroupOpacity = YES; // required for touch handling
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
- (RCTShadowView *)createShadowViewWithTag:(NSNumber *)tag
|
||||
{
|
||||
RCTShadowView *shadowView = [_manager shadowView];
|
||||
shadowView.reactTag = tag;
|
||||
shadowView.viewName = _name;
|
||||
return shadowView;
|
||||
}
|
||||
|
||||
- (RCTPropBlock)propBlockForKey:(NSString *)name defaultView:(id)defaultView
|
||||
{
|
||||
BOOL shadowView = [defaultView isKindOfClass:[RCTShadowView class]];
|
||||
NSMutableDictionary *propBlocks = shadowView ? _shadowPropBlocks : _viewPropBlocks;
|
||||
RCTPropBlock propBlock = propBlocks[name];
|
||||
if (!propBlock) {
|
||||
|
||||
__weak RCTComponentData *weakSelf = self;
|
||||
|
||||
// Get type
|
||||
SEL type = NULL;
|
||||
NSString *keyPath = nil;
|
||||
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"propConfig%@_%@", shadowView ? @"Shadow" : @"", name]);
|
||||
Class managerClass = [_manager class];
|
||||
if ([managerClass respondsToSelector:selector]) {
|
||||
NSArray *typeAndKeyPath = ((NSArray *(*)(id, SEL))objc_msgSend)(managerClass, selector);
|
||||
type = NSSelectorFromString([typeAndKeyPath[0] stringByAppendingString:@":"]);
|
||||
keyPath = typeAndKeyPath.count > 1 ? typeAndKeyPath[1] : nil;
|
||||
} else {
|
||||
propBlock = ^(__unused id view, __unused id json) {};
|
||||
propBlocks[name] = propBlock;
|
||||
return propBlock;
|
||||
}
|
||||
|
||||
// Check for custom setter
|
||||
if ([keyPath isEqualToString:@"__custom__"]) {
|
||||
|
||||
// Get custom setter
|
||||
SEL customSetter = NSSelectorFromString([NSString stringWithFormat:@"set_%@:for%@View:withDefaultView:", name, shadowView ? @"Shadow" : @""]);
|
||||
|
||||
propBlock = ^(id<RCTComponent> view, id json) {
|
||||
((void (*)(id, SEL, id, id, id))objc_msgSend)(
|
||||
weakSelf.manager, customSetter, json == (id)kCFNull ? nil : json, view, defaultView
|
||||
);
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
// Disect keypath
|
||||
NSString *key = name;
|
||||
NSArray *parts = [keyPath componentsSeparatedByString:@"."];
|
||||
if (parts) {
|
||||
key = [parts lastObject];
|
||||
parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];
|
||||
}
|
||||
|
||||
// Get property getter
|
||||
SEL getter = NSSelectorFromString(key);
|
||||
|
||||
// Get property setter
|
||||
SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",
|
||||
[[key substringToIndex:1] uppercaseString],
|
||||
[key substringFromIndex:1]]);
|
||||
|
||||
// Build setter block
|
||||
void (^setterBlock)(id target, id source, id json) = nil;
|
||||
NSMethodSignature *typeSignature = [[RCTConvert class] methodSignatureForSelector:type];
|
||||
switch (typeSignature.methodReturnType[0]) {
|
||||
|
||||
#define RCT_CASE(_value, _type) \
|
||||
case _value: { \
|
||||
_type (*convert)(id, SEL, id) = (typeof(convert))objc_msgSend; \
|
||||
_type (*get)(id, SEL) = (typeof(get))objc_msgSend; \
|
||||
void (*set)(id, SEL, _type) = (typeof(set))objc_msgSend; \
|
||||
setterBlock = ^(id target, id source, id json) { \
|
||||
set(target, setter, json ? convert([RCTConvert class], type, json) : get(source, getter)); \
|
||||
}; \
|
||||
break; \
|
||||
}
|
||||
|
||||
RCT_CASE(_C_SEL, SEL)
|
||||
RCT_CASE(_C_CHARPTR, const char *)
|
||||
RCT_CASE(_C_CHR, char)
|
||||
RCT_CASE(_C_UCHR, unsigned char)
|
||||
RCT_CASE(_C_SHT, short)
|
||||
RCT_CASE(_C_USHT, unsigned short)
|
||||
RCT_CASE(_C_INT, int)
|
||||
RCT_CASE(_C_UINT, unsigned int)
|
||||
RCT_CASE(_C_LNG, long)
|
||||
RCT_CASE(_C_ULNG, unsigned long)
|
||||
RCT_CASE(_C_LNG_LNG, long long)
|
||||
RCT_CASE(_C_ULNG_LNG, unsigned long long)
|
||||
RCT_CASE(_C_FLT, float)
|
||||
RCT_CASE(_C_DBL, double)
|
||||
RCT_CASE(_C_BOOL, BOOL)
|
||||
RCT_CASE(_C_PTR, void *)
|
||||
RCT_CASE(_C_ID, id)
|
||||
|
||||
case _C_STRUCT_B:
|
||||
default: {
|
||||
|
||||
NSInvocation *typeInvocation = [NSInvocation invocationWithMethodSignature:typeSignature];
|
||||
[typeInvocation setSelector:type];
|
||||
[typeInvocation setTarget:[RCTConvert class]];
|
||||
|
||||
__block NSInvocation *sourceInvocation = nil;
|
||||
__block NSInvocation *targetInvocation = nil;
|
||||
|
||||
setterBlock = ^(id target, id source, id json) { \
|
||||
|
||||
// Get value
|
||||
void *value = malloc(typeSignature.methodReturnLength);
|
||||
if (json) {
|
||||
[typeInvocation setArgument:&json atIndex:2];
|
||||
[typeInvocation invoke];
|
||||
[typeInvocation getReturnValue:value];
|
||||
} else {
|
||||
if (!sourceInvocation && source) {
|
||||
NSMethodSignature *signature = [source methodSignatureForSelector:getter];
|
||||
sourceInvocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
[sourceInvocation setSelector:getter];
|
||||
}
|
||||
[sourceInvocation invokeWithTarget:source];
|
||||
[sourceInvocation getReturnValue:value];
|
||||
}
|
||||
|
||||
// Set value
|
||||
if (!targetInvocation && target) {
|
||||
NSMethodSignature *signature = [target methodSignatureForSelector:setter];
|
||||
targetInvocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
[targetInvocation setSelector:setter];
|
||||
}
|
||||
[targetInvocation setArgument:value atIndex:2];
|
||||
[targetInvocation invokeWithTarget:target];
|
||||
free(value);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
propBlock = ^(__unused id view, __unused id json) {
|
||||
|
||||
// Follow keypath
|
||||
id target = view;
|
||||
for (NSString *part in parts) {
|
||||
target = [target valueForKey:part];
|
||||
}
|
||||
|
||||
if (json == (id)kCFNull) {
|
||||
|
||||
// Copy default property
|
||||
id source = defaultView;
|
||||
for (NSString *part in parts) {
|
||||
source = [source valueForKey:part];
|
||||
}
|
||||
setterBlock(target, source, nil);
|
||||
|
||||
} else {
|
||||
|
||||
// Set property with json
|
||||
setterBlock(target, nil, json);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (RCT_DEBUG) {
|
||||
|
||||
// Provide more useful log feedback if there's an error
|
||||
RCTPropBlock unwrappedBlock = propBlock;
|
||||
propBlock = ^(id<RCTComponent> view, id json) {
|
||||
NSString *logPrefix = [NSString stringWithFormat:
|
||||
@"Error setting property '%@' of %@ with tag #%@: ",
|
||||
name, weakSelf.name, view.reactTag];
|
||||
|
||||
RCTPerformBlockWithLogPrefix(^{ unwrappedBlock(view, json); }, logPrefix);
|
||||
};
|
||||
}
|
||||
|
||||
propBlocks[name] = [propBlock copy];
|
||||
}
|
||||
return propBlock;
|
||||
}
|
||||
|
||||
- (void)setProps:(NSDictionary *)props forView:(id<RCTComponent>)view
|
||||
{
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_defaultView) {
|
||||
_defaultView = [self createViewWithTag:nil];
|
||||
}
|
||||
|
||||
[props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, __unused BOOL *stop) {
|
||||
[self propBlockForKey:key defaultView:_defaultView](view, json);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setProps:(NSDictionary *)props forShadowView:(RCTShadowView *)shadowView
|
||||
{
|
||||
if (!shadowView) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_defaultShadowView) {
|
||||
_defaultShadowView = [self createShadowViewWithTag:nil];
|
||||
}
|
||||
|
||||
[props enumerateKeysAndObjectsUsingBlock:^(NSString *key, id json, __unused BOOL *stop) {
|
||||
[self propBlockForKey:key defaultView:_defaultShadowView](shadowView, json);
|
||||
}];
|
||||
|
||||
[shadowView updateLayout];
|
||||
}
|
||||
|
||||
- (NSDictionary *)viewConfig
|
||||
{
|
||||
Class managerClass = [_manager class];
|
||||
NSMutableDictionary *propTypes = [[NSMutableDictionary alloc] init];
|
||||
|
||||
unsigned int count = 0;
|
||||
Method *methods = class_copyMethodList(object_getClass(managerClass), &count);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
Method method = methods[i];
|
||||
SEL selector = method_getName(method);
|
||||
NSString *methodName = NSStringFromSelector(selector);
|
||||
if ([methodName hasPrefix:@"propConfig"]) {
|
||||
NSRange nameRange = [methodName rangeOfString:@"_"];
|
||||
if (nameRange.length) {
|
||||
NSString *name = [methodName substringFromIndex:nameRange.location + 1];
|
||||
NSString *type = ((NSArray *(*)(id, SEL))objc_msgSend)(managerClass, selector)[0];
|
||||
if (RCT_DEBUG && propTypes[name] && ![propTypes[name] isEqualToString:type]) {
|
||||
RCTLogError(@"Property '%@' of component '%@' redefined from '%@' "
|
||||
"to '%@'", name, _name, propTypes[name], type);
|
||||
}
|
||||
propTypes[name] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(methods);
|
||||
|
||||
return propTypes;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -25,6 +25,7 @@
|
||||
}
|
||||
|
||||
RCT_NOT_IMPLEMENTED(-initWithFrame:(CGRect)frame)
|
||||
RCT_NOT_IMPLEMENTED(-initWithCoder:coder)
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "Layout.h"
|
||||
#import "RCTViewNodeProtocol.h"
|
||||
#import "RCTComponent.h"
|
||||
|
||||
@class RCTSparseArray;
|
||||
|
||||
@@ -32,14 +32,14 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
|
||||
* 3. If a node is "computed" and the constraint passed from above is identical to the constraint used to
|
||||
* perform the last computation, we skip laying out the subtree entirely.
|
||||
*/
|
||||
@interface RCTShadowView : NSObject <RCTViewNodeProtocol>
|
||||
@interface RCTShadowView : NSObject <RCTComponent>
|
||||
|
||||
@property (nonatomic, weak, readonly) RCTShadowView *superview;
|
||||
@property (nonatomic, assign, readonly) css_node_t *cssNode;
|
||||
@property (nonatomic, copy) NSString *viewName;
|
||||
@property (nonatomic, strong) UIColor *backgroundColor; // Used to propagate to children
|
||||
@property (nonatomic, assign) RCTUpdateLifecycle layoutLifecycle;
|
||||
@property (nonatomic, assign) BOOL hasOnLayout;
|
||||
@property (nonatomic, assign, getter=hasOnLayout) BOOL onLayout;
|
||||
|
||||
/**
|
||||
* isNewView - Used to track the first time the view is introduced into the hierarchy. It is initialized YES, then is
|
||||
@@ -104,7 +104,7 @@ typedef void (^RCTApplierBlock)(RCTSparseArray *viewRegistry);
|
||||
@property (nonatomic, assign) css_justify_t justifyContent;
|
||||
@property (nonatomic, assign) css_align_t alignSelf;
|
||||
@property (nonatomic, assign) css_align_t alignItems;
|
||||
@property (nonatomic, assign) css_position_type_t positionType;
|
||||
@property (nonatomic, assign) css_position_type_t position;
|
||||
@property (nonatomic, assign) css_wrap_type_t flexWrap;
|
||||
@property (nonatomic, assign) CGFloat flex;
|
||||
|
||||
|
||||
@@ -541,7 +541,7 @@ RCT_STYLE_PROPERTY(FlexDirection, flexDirection, flex_direction, css_flex_direct
|
||||
RCT_STYLE_PROPERTY(JustifyContent, justifyContent, justify_content, css_justify_t)
|
||||
RCT_STYLE_PROPERTY(AlignSelf, alignSelf, align_self, css_align_t)
|
||||
RCT_STYLE_PROPERTY(AlignItems, alignItems, align_items, css_align_t)
|
||||
RCT_STYLE_PROPERTY(PositionType, positionType, position_type, css_position_type_t)
|
||||
RCT_STYLE_PROPERTY(Position, position, position_type, css_position_type_t)
|
||||
RCT_STYLE_PROPERTY(FlexWrap, flexWrap, flex_wrap, css_wrap_type_t)
|
||||
|
||||
- (void)setBackgroundColor:(UIColor *)color
|
||||
|
||||
@@ -21,11 +21,6 @@
|
||||
|
||||
typedef void (^RCTViewManagerUIBlock)(RCTUIManager *uiManager, RCTSparseArray *viewRegistry);
|
||||
|
||||
/**
|
||||
* Underlying implementation of RCT_EXPORT_XXX macros. Ignore this.
|
||||
*/
|
||||
RCT_EXTERN void RCTSetViewProperty(NSString *, NSString *, SEL, id, id, id);
|
||||
|
||||
@interface RCTViewManager : NSObject <RCTBridgeModule>
|
||||
|
||||
/**
|
||||
@@ -105,35 +100,28 @@ RCT_EXTERN void RCTSetViewProperty(NSString *, NSString *, SEL, id, id, id);
|
||||
/**
|
||||
* This handles the simple case, where JS and native property names match.
|
||||
*/
|
||||
#define RCT_EXPORT_VIEW_PROPERTY(name, type) RCT_REMAP_VIEW_PROPERTY(name, name, type)
|
||||
|
||||
#define RCT_EXPORT_SHADOW_PROPERTY(name, type) RCT_REMAP_SHADOW_PROPERTY(name, name, type)
|
||||
#define RCT_EXPORT_VIEW_PROPERTY(name, type) \
|
||||
+ (NSArray *)propConfig_##name { return @[@#type]; }
|
||||
|
||||
/**
|
||||
* This macro maps a named property on the module to an arbitrary key path
|
||||
* within the view or shadowView.
|
||||
* This macro maps a named property to an arbitrary key path in the view.
|
||||
*/
|
||||
#define RCT_REMAP_VIEW_PROPERTY(name, keyPath, type) \
|
||||
RCT_CUSTOM_VIEW_PROPERTY(name, type, UIView) { \
|
||||
RCTSetViewProperty(@#name, @#keyPath, @selector(type:), view, defaultView, json); \
|
||||
}
|
||||
|
||||
#define RCT_REMAP_SHADOW_PROPERTY(name, keyPath, type) \
|
||||
RCT_CUSTOM_SHADOW_PROPERTY(name, type, RCTShadowView) { \
|
||||
RCTSetViewProperty(@#name, @#keyPath, @selector(type:), view, defaultView, json); \
|
||||
}
|
||||
#define RCT_REMAP_VIEW_PROPERTY(name, keyPath, type) \
|
||||
+ (NSArray *)propConfig_##name { return @[@#type, @#keyPath]; }
|
||||
|
||||
/**
|
||||
* These macros can be used when you need to provide custom logic for setting
|
||||
* This macro can be used when you need to provide custom logic for setting
|
||||
* view properties. The macro should be followed by a method body, which can
|
||||
* refer to "json", "view" and "defaultView" to implement the required logic.
|
||||
*/
|
||||
#define RCT_CUSTOM_VIEW_PROPERTY(name, type, viewClass) \
|
||||
+ (NSString *)getPropConfigView_##name { return @#type; } \
|
||||
RCT_REMAP_VIEW_PROPERTY(name, __custom__, type) \
|
||||
- (void)set_##name:(id)json forView:(viewClass *)view withDefaultView:(viewClass *)defaultView
|
||||
|
||||
#define RCT_CUSTOM_SHADOW_PROPERTY(name, type, viewClass) \
|
||||
+ (NSString *)getPropConfigShadow_##name { return @#type; } \
|
||||
- (void)set_##name:(id)json forShadowView:(viewClass *)view withDefaultView:(viewClass *)defaultView
|
||||
/**
|
||||
* This macro is used to map properties to the shadow view, instead of the view.
|
||||
*/
|
||||
#define RCT_EXPORT_SHADOW_PROPERTY(name, type) \
|
||||
+ (NSArray *)propConfigShadow_##name { return @[@#type]; }
|
||||
|
||||
@end
|
||||
|
||||
@@ -43,15 +43,6 @@ RCT_MULTI_ENUM_CONVERTER(UIAccessibilityTraits, (@{
|
||||
|
||||
@end
|
||||
|
||||
void RCTSetViewProperty(NSString *name, NSString *keyPath, SEL type,
|
||||
id view, id defaultView, id json)
|
||||
{
|
||||
if ((json && !RCTSetProperty(view, keyPath, type, json)) ||
|
||||
(!json && !RCTCopyProperty(view, defaultView, keyPath))) {
|
||||
RCTLogError(@"%@ does not have setter for `%@` property", [view class], name);
|
||||
}
|
||||
}
|
||||
|
||||
@implementation RCTViewManager
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@@ -273,8 +264,8 @@ RCT_EXPORT_SHADOW_PROPERTY(flexWrap, css_wrap_type_t)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(justifyContent, css_justify_t)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(alignItems, css_align_t)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(alignSelf, css_align_t)
|
||||
RCT_REMAP_SHADOW_PROPERTY(position, positionType, css_position_type_t)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(position, css_position_type_t)
|
||||
|
||||
RCT_REMAP_SHADOW_PROPERTY(onLayout, hasOnLayout, BOOL)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(onLayout, BOOL)
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTViewNodeProtocol.h"
|
||||
#import "RCTComponent.h"
|
||||
|
||||
//TODO: let's try to eliminate this category if possible
|
||||
|
||||
@interface UIView (React) <RCTViewNodeProtocol>
|
||||
@interface UIView (React) <RCTComponent>
|
||||
|
||||
/**
|
||||
* Used by the UIIManager to set the view frame.
|
||||
|
||||
Reference in New Issue
Block a user