2015-02-03 updates
- Add back providesModule transform to JSAppServer | Joseph Savona - [ReactKit] fix open source performance issue | John Harper - [ReactKit] improve ReactIOSEventEmitter logics | Andrew Rasmussen - [reactkit] fix web view JS executor and bind it to Command-d | John Harper - Removed hardcoded RCTModuleIDs | Nick Lockwood - [ReactKit] Animated GIF support | Alex Akers - [ReactKit] Update RCTBridge to support non-`id` argument types | Alex Akers - [reactkit] fix typo in RCTCopyProperty() change | John Harper - [reactkit] fix shadow view crash on missing properties | John Harper - [reactkit] fix transform keypath | John Harper
This commit is contained in:
parent
ccd8f184af
commit
6153fffb30
|
@ -9,6 +9,7 @@
|
|||
var React = require('react-native');
|
||||
var {
|
||||
Bundler,
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
|
@ -118,13 +119,22 @@ var Cell = React.createClass({
|
|||
}
|
||||
},
|
||||
|
||||
imageContents() {
|
||||
switch (this.props.player) {
|
||||
case 1:
|
||||
return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-277623.gif';
|
||||
case 2:
|
||||
return 'http://www.picgifs.com/alphabets/alphabets/children-5/alphabets-children-5-730492.gif';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TouchableHighlight onPress={this.props.onPress} underlayColor={'clear'} activeOpacity={0.5}>
|
||||
<View style={[styles.cell, this.cellStyle()]}>
|
||||
<Text style={[styles.cellText, this.textStyle()]}>
|
||||
{this.textContents()}
|
||||
</Text>
|
||||
<Image source={{uri: this.imageContents()}} />
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
|
|
@ -169,12 +169,20 @@ var ReactIOSEventEmitter = merge(ReactEventEmitterMixin, {
|
|||
var target = nativeEvent.target;
|
||||
if (target !== null && target !== undefined) {
|
||||
if (target < ReactIOSTagHandles.tagsStartAt) {
|
||||
// When we get multiple touches at the same time, only the first touch
|
||||
// actually has a view attached to it. The rest of the touches do not.
|
||||
// This is presumably because iOS doesn't want to send touch events to
|
||||
// two views for a single multi touch. Therefore this warning is only
|
||||
// appropriate when it happens to the first touch. (hence jj === 0)
|
||||
if (__DEV__) {
|
||||
if (jj === 0) {
|
||||
warning(
|
||||
false,
|
||||
'A view is reporting that a touch occured on tag zero.'
|
||||
);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
rootNodeID = NodeHandle.getRootNodeID(target);
|
||||
}
|
||||
|
|
|
@ -37,12 +37,14 @@ function createStrictShapeTypeChecker(shapeTypes) {
|
|||
var allKeys = merge(props[propName], shapeTypes);
|
||||
for (var key in allKeys) {
|
||||
var checker = shapeTypes[key];
|
||||
if (!checker) {
|
||||
invariant(
|
||||
checker,
|
||||
false,
|
||||
`Invalid props.${propName} key \`${key}\` supplied to \`${componentName}\`.` +
|
||||
`\nBad object: ` + JSON.stringify(props[propName], null, ' ') +
|
||||
`\nValid keys: ` + JSON.stringify(Object.keys(shapeTypes), null, ' ')
|
||||
);
|
||||
}
|
||||
var error = checker(propValue, key, componentName, location);
|
||||
if (error) {
|
||||
invariant(
|
||||
|
|
|
@ -33,10 +33,9 @@ static inline NSDictionary *RCTAPIErrorObject(NSString *msg)
|
|||
*/
|
||||
@interface RCTBridge : NSObject <RCTInvalidating>
|
||||
|
||||
- (instancetype)initWithJavaScriptExecutor:(id<RCTJavaScriptExecutor>)javaScriptExecutor
|
||||
javaScriptModulesConfig:(NSDictionary *)javaScriptModulesConfig;
|
||||
- (instancetype)initWithJavaScriptExecutor:(id<RCTJavaScriptExecutor>)javaScriptExecutor;
|
||||
|
||||
- (void)enqueueJSCall:(NSUInteger)moduleID methodID:(NSUInteger)methodID args:(NSArray *)args;
|
||||
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args;
|
||||
- (void)enqueueApplicationScript:(NSString *)script url:(NSURL *)url onComplete:(RCTJavaScriptCompleteBlock)onComplete;
|
||||
|
||||
@property (nonatomic, readonly) RCTEventDispatcher *eventDispatcher;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#import "RCTInvalidating.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTModuleIDs.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
/**
|
||||
|
@ -36,19 +35,6 @@ typedef NS_ENUM(NSUInteger, RCTBridgeFields) {
|
|||
RCTBridgeFieldFlushDateMillis
|
||||
};
|
||||
|
||||
static NSString *RCTModuleName(Class moduleClass)
|
||||
{
|
||||
if ([moduleClass respondsToSelector:@selector(moduleName)]) {
|
||||
|
||||
return [moduleClass moduleName];
|
||||
|
||||
} else {
|
||||
|
||||
// Default implementation, works in most cases
|
||||
return NSStringFromClass(moduleClass);
|
||||
}
|
||||
}
|
||||
|
||||
static NSDictionary *RCTNativeModuleClasses(void)
|
||||
{
|
||||
static NSMutableDictionary *modules;
|
||||
|
@ -73,7 +59,7 @@ static NSDictionary *RCTNativeModuleClasses(void)
|
|||
}
|
||||
|
||||
// Get module name
|
||||
NSString *moduleName = RCTModuleName(cls);
|
||||
NSString *moduleName = [cls respondsToSelector:@selector(moduleName)] ? [cls moduleName] : NSStringFromClass(cls);
|
||||
|
||||
// Check module name is unique
|
||||
id existingClass = modules[moduleName];
|
||||
|
@ -90,23 +76,22 @@ static NSDictionary *RCTNativeModuleClasses(void)
|
|||
@implementation RCTBridge
|
||||
{
|
||||
NSMutableDictionary *_moduleInstances;
|
||||
NSDictionary *_javaScriptModulesConfig;
|
||||
NSMutableDictionary *_moduleIDLookup;
|
||||
NSMutableDictionary *_methodIDLookup;
|
||||
id<RCTJavaScriptExecutor> _javaScriptExecutor;
|
||||
}
|
||||
|
||||
static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
||||
|
||||
- (instancetype)initWithJavaScriptExecutor:(id<RCTJavaScriptExecutor>)javaScriptExecutor
|
||||
javaScriptModulesConfig:(NSDictionary *)javaScriptModulesConfig
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_javaScriptExecutor = javaScriptExecutor;
|
||||
_latestJSExecutor = _javaScriptExecutor;
|
||||
_eventDispatcher = [[RCTEventDispatcher alloc] initWithBridge:self];
|
||||
_javaScriptModulesConfig = javaScriptModulesConfig;
|
||||
_shadowQueue = dispatch_queue_create("com.facebook.ReactKit.ShadowQueue", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
// Register modules
|
||||
// Instantiate modules
|
||||
_moduleInstances = [[NSMutableDictionary alloc] init];
|
||||
[RCTNativeModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, Class moduleClass, BOOL *stop) {
|
||||
if (_moduleInstances[moduleName] == nil) {
|
||||
|
@ -118,6 +103,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
}
|
||||
}];
|
||||
|
||||
_moduleIDLookup = [[NSMutableDictionary alloc] init];
|
||||
_methodIDLookup = [[NSMutableDictionary alloc] init];
|
||||
[self doneRegisteringModules];
|
||||
}
|
||||
|
||||
|
@ -168,10 +155,18 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
/**
|
||||
* Like JS::call, for objective-c.
|
||||
*/
|
||||
- (void)enqueueJSCall:(NSUInteger)moduleID methodID:(NSUInteger)methodID args:(NSArray *)args
|
||||
- (void)enqueueJSCall:(NSString *)moduleDotMethod args:(NSArray *)args
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
[self _invokeRemoteJSModule:moduleID methodID:methodID args:args];
|
||||
NSNumber *moduleID = _moduleIDLookup[moduleDotMethod];
|
||||
RCTAssert(moduleID, @"Module '%@' not registered.",
|
||||
[[moduleDotMethod componentsSeparatedByString:@"."] firstObject]);
|
||||
|
||||
NSNumber *methodID = _methodIDLookup[moduleDotMethod];
|
||||
RCTAssert(methodID, @"Method '%@' not registered.", moduleDotMethod);
|
||||
|
||||
[self _invokeAndProcessModule:@"BatchedBridge"
|
||||
method:@"callFunctionReturnFlushedQueue"
|
||||
arguments:@[moduleID, methodID, args]];
|
||||
}
|
||||
|
||||
- (void)enqueueApplicationScript:(NSString *)script url:(NSURL *)url onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||
|
@ -217,13 +212,6 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
callback:processResponse];
|
||||
}
|
||||
|
||||
- (void)_invokeRemoteJSModule:(NSUInteger)moduleID methodID:(NSUInteger)methodID args:(NSArray *)args
|
||||
{
|
||||
[self _invokeAndProcessModule:@"BatchedBridge"
|
||||
method:@"callFunctionReturnFlushedQueue"
|
||||
arguments:@[@(moduleID), @(methodID), args]];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO (#5906496): Have responses piggy backed on a round trip with ObjC->JS requests.
|
||||
*/
|
||||
|
@ -334,19 +322,19 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
return;
|
||||
}
|
||||
|
||||
NSInvocation *invocation = [RCTBridge invocationForAdditionalArguments:methodArity];
|
||||
|
||||
// TODO: we should just store module instances by index, since that's how we look them up anyway
|
||||
id target = strongSelf->_moduleInstances[moduleName];
|
||||
RCTAssert(target != nil, @"No module found for name '%@'", moduleName);
|
||||
|
||||
[invocation setArgument:&target atIndex:0];
|
||||
|
||||
SEL selector = method.selector;
|
||||
|
||||
NSMethodSignature *methodSignature = [target methodSignatureForSelector:selector];
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
|
||||
[invocation setArgument:&target atIndex:0];
|
||||
[invocation setArgument:&selector atIndex:1];
|
||||
|
||||
// Retain used blocks until after invocation completes.
|
||||
NSMutableArray *blocks = [NSMutableArray array];
|
||||
NS_VALID_UNTIL_END_OF_SCOPE NSMutableArray *blocks = [NSMutableArray array];
|
||||
|
||||
[params enumerateObjectsUsingBlock:^(id param, NSUInteger idx, BOOL *stop) {
|
||||
if ([param isEqual:[NSNull null]]) {
|
||||
|
@ -357,7 +345,57 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
param = block;
|
||||
}
|
||||
|
||||
[invocation setArgument:¶m atIndex:idx + 2];
|
||||
NSUInteger argIdx = idx + 2;
|
||||
|
||||
BOOL shouldSet = YES;
|
||||
const char *argumentType = [methodSignature getArgumentTypeAtIndex:argIdx];
|
||||
switch (argumentType[0]) {
|
||||
case ':':
|
||||
if ([param isKindOfClass:[NSString class]]) {
|
||||
SEL selector = NSSelectorFromString(param);
|
||||
[invocation setArgument:&selector atIndex:argIdx];
|
||||
shouldSet = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if ([param isKindOfClass:[NSString class]]) {
|
||||
const char *string = [param UTF8String];
|
||||
[invocation setArgument:&string atIndex:argIdx];
|
||||
shouldSet = NO;
|
||||
}
|
||||
break;
|
||||
|
||||
#define CASE(_value, _type, _selector) \
|
||||
case _value: \
|
||||
if ([param respondsToSelector:@selector(_selector)]) { \
|
||||
_type value = [param _selector]; \
|
||||
[invocation setArgument:&value atIndex:argIdx]; \
|
||||
shouldSet = NO; \
|
||||
} \
|
||||
break;
|
||||
|
||||
CASE('c', char, charValue)
|
||||
CASE('C', unsigned char, unsignedCharValue)
|
||||
CASE('s', short, shortValue)
|
||||
CASE('S', unsigned short, unsignedShortValue)
|
||||
CASE('i', int, intValue)
|
||||
CASE('I', unsigned int, unsignedIntValue)
|
||||
CASE('l', long, longValue)
|
||||
CASE('L', unsigned long, unsignedLongValue)
|
||||
CASE('q', long long, longLongValue)
|
||||
CASE('Q', unsigned long long, unsignedLongLongValue)
|
||||
CASE('f', float, floatValue)
|
||||
CASE('d', double, doubleValue)
|
||||
CASE('B', BOOL, boolValue)
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (shouldSet) {
|
||||
[invocation setArgument:¶m atIndex:argIdx];
|
||||
}
|
||||
}];
|
||||
|
||||
@try {
|
||||
|
@ -366,10 +404,6 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
@catch (NSException *exception) {
|
||||
RCTLogMustFix(@"Exception thrown while invoking %@ on target %@ with params %@: %@", method.JSMethodName, target, params, exception);
|
||||
}
|
||||
@finally {
|
||||
// Force `blocks` to remain alive until here.
|
||||
blocks = nil;
|
||||
}
|
||||
});
|
||||
|
||||
return YES;
|
||||
|
@ -412,16 +446,71 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
return invocation;
|
||||
}
|
||||
|
||||
- (NSArray *)JSMethods
|
||||
{
|
||||
NSMutableArray *methods = [[NSMutableArray alloc] init];
|
||||
|
||||
// Add globally used methods
|
||||
[methods addObjectsFromArray:@[
|
||||
@"Bundler.runApplication",
|
||||
@"RCTEventEmitter.receiveEvent",
|
||||
@"RCTEventEmitter.receiveTouches",
|
||||
]];
|
||||
|
||||
// NOTE: these methods are currently unused in the OSS project
|
||||
// @"Dimensions.set",
|
||||
// @"RCTDeviceEventEmitter.emit",
|
||||
// @"RCTNativeAppEventEmitter.emit",
|
||||
// @"ReactIOS.unmountComponentAtNodeAndRemoveContainer",
|
||||
|
||||
// Register individual methods from modules
|
||||
for (Class cls in RCTNativeModuleClasses().allValues) {
|
||||
if (RCTClassOverridesClassMethod(cls, @selector(JSMethods))) {
|
||||
[methods addObjectsFromArray:[cls JSMethods]];
|
||||
}
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
- (void)doneRegisteringModules
|
||||
{
|
||||
// TODO: everything in this method can actually be determined
|
||||
// statically from just the class, and can therefore be cached
|
||||
// in a dispatch_once instead of being repeated every time we
|
||||
// reload or create a new RootView.
|
||||
|
||||
RCTAssertMainThread();
|
||||
RCTAssert(_javaScriptModulesConfig != nil, @"JS module config not loaded in APP");
|
||||
|
||||
NSMutableDictionary *objectsToInject = [NSMutableDictionary dictionary];
|
||||
/**
|
||||
* This constructs the remote modules configuration data structure,
|
||||
* which represents the native modules and methods that will be called
|
||||
* by JS. A numeric ID is assigned to each module and method, which will
|
||||
* be used to communicate via the bridge. The structure of each
|
||||
* module is as follows:
|
||||
*
|
||||
* "ModuleName1": {
|
||||
* "moduleID": 0,
|
||||
* "methods": {
|
||||
* "methodName1": {
|
||||
* "methodID": 0,
|
||||
* "type": "remote"
|
||||
* },
|
||||
* "methodName2": {
|
||||
* "methodID": 1,
|
||||
* "type": "remote"
|
||||
* },
|
||||
* etc...
|
||||
* },
|
||||
* "constants": {
|
||||
* ...
|
||||
* }
|
||||
* },
|
||||
* etc...
|
||||
*/
|
||||
|
||||
// Dictionary of { moduleName0: { moduleID: 0, methods: { methodName0: { methodID: 0, type: remote }, methodName1: { ... }, ... }, ... }
|
||||
NSUInteger moduleCount = RCTExportedMethodsByModule().count;
|
||||
NSMutableDictionary *moduleConfigs = [NSMutableDictionary dictionaryWithCapacity:RCTExportedMethodsByModule().count];
|
||||
NSMutableDictionary *remoteModules = [NSMutableDictionary dictionaryWithCapacity:RCTExportedMethodsByModule().count];
|
||||
for (NSUInteger i = 0; i < moduleCount; i++) {
|
||||
NSString *moduleName = RCTExportedModuleNameAtSortedIndex(i);
|
||||
NSArray *rawMethods = RCTExportedMethodsByModule()[moduleName];
|
||||
|
@ -433,36 +522,88 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
|
|||
};
|
||||
}];
|
||||
|
||||
NSMutableDictionary *moduleConfig = [NSMutableDictionary dictionary];
|
||||
moduleConfig[@"moduleID"] = @(i);
|
||||
moduleConfig[@"methods"] = methods;
|
||||
|
||||
id target = [_moduleInstances objectForKey:moduleName];
|
||||
if ([target respondsToSelector:@selector(constantsToExport)]) {
|
||||
moduleConfig[@"constants"] = [target constantsToExport];
|
||||
}
|
||||
moduleConfigs[moduleName] = moduleConfig;
|
||||
}
|
||||
NSDictionary *batchedBridgeConfig = @{
|
||||
@"remoteModuleConfig": moduleConfigs,
|
||||
@"localModulesConfig": _javaScriptModulesConfig
|
||||
NSDictionary *module = @{
|
||||
@"moduleID": @(i),
|
||||
@"methods": methods
|
||||
};
|
||||
|
||||
NSString *configJSON = RCTJSONStringify(batchedBridgeConfig, NULL);
|
||||
objectsToInject[@"__fbBatchedBridgeConfig"] = configJSON;
|
||||
id target = _moduleInstances[moduleName];
|
||||
if (RCTClassOverridesClassMethod([target class], @selector(constantsToExport))) {
|
||||
module = [module mutableCopy];
|
||||
((NSMutableDictionary *)module)[@"constants"] = [[target class] constantsToExport];
|
||||
}
|
||||
remoteModules[moduleName] = module;
|
||||
}
|
||||
|
||||
/**
|
||||
* As above, but for local modules/methods, which represent JS classes
|
||||
* and methods that will be called by the native code via the bridge.
|
||||
* Structure is essentially the same as for remote modules:
|
||||
*
|
||||
* "ModuleName1": {
|
||||
* "moduleID": 0,
|
||||
* "methods": {
|
||||
* "methodName1": {
|
||||
* "methodID": 0,
|
||||
* "type": "local"
|
||||
* },
|
||||
* "methodName2": {
|
||||
* "methodID": 1,
|
||||
* "type": "local"
|
||||
* },
|
||||
* etc...
|
||||
* }
|
||||
* },
|
||||
* etc...
|
||||
*/
|
||||
|
||||
NSMutableDictionary *localModules = [[NSMutableDictionary alloc] init];
|
||||
for (NSString *moduleDotMethod in [self JSMethods]) {
|
||||
|
||||
NSArray *parts = [moduleDotMethod componentsSeparatedByString:@"."];
|
||||
RCTAssert(parts.count == 2, @"'%@' is not a valid JS method definition - expected 'Module.method' format.", moduleDotMethod);
|
||||
|
||||
// Add module if it doesn't already exist
|
||||
NSString *moduleName = parts[0];
|
||||
NSDictionary *module = localModules[moduleName];
|
||||
if (!module) {
|
||||
module = @{
|
||||
@"moduleID": @(localModules.count),
|
||||
@"methods": [[NSMutableDictionary alloc] init]
|
||||
};
|
||||
localModules[moduleName] = module;
|
||||
}
|
||||
|
||||
// Add method if it doesn't already exist
|
||||
NSString *methodName = parts[1];
|
||||
NSMutableDictionary *methods = module[@"methods"];
|
||||
if (!methods[methodName]) {
|
||||
methods[methodName] = @{
|
||||
@"methodID": @(methods.count),
|
||||
@"type": @"local"
|
||||
};
|
||||
}
|
||||
|
||||
// Add module and method lookup
|
||||
_moduleIDLookup[moduleDotMethod] = module[@"moduleID"];
|
||||
_methodIDLookup[moduleDotMethod] = methods[methodName][@"methodID"];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject module data into JS context
|
||||
*/
|
||||
NSString *configJSON = RCTJSONStringify(@{
|
||||
@"remoteModuleConfig": remoteModules,
|
||||
@"localModulesConfig": localModules
|
||||
}, NULL);
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
[objectsToInject enumerateKeysAndObjectsUsingBlock:^(NSString *objectName, NSString *script, BOOL *stop) {
|
||||
[_javaScriptExecutor injectJSONText:script asGlobalObjectNamed:objectName callback:^(id err) {
|
||||
[_javaScriptExecutor injectJSONText:configJSON asGlobalObjectNamed:@"__fbBatchedBridgeConfig" callback:^(id err) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
}];
|
||||
|
||||
for (NSUInteger i = 0, count = objectsToInject.count; i < count; i++) {
|
||||
if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC)) != 0) {
|
||||
RCTLogMustFix(@"JavaScriptExecutor take too long to inject JSON object");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)registerRootView:(RCTRootView *)rootView
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
+ (UIColor *)UIColor:(id)json;
|
||||
+ (CGColorRef)CGColor:(id)json;
|
||||
|
||||
+ (CAKeyframeAnimation *)GIF:(id)json;
|
||||
+ (UIImage *)UIImage:(id)json;
|
||||
+ (CGImageRef)CGImage:(id)json;
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#import "RCTConvert.h"
|
||||
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
|
||||
#import "RCTLog.h"
|
||||
|
||||
CGFloat const RCTDefaultFontSize = 14;
|
||||
|
@ -426,6 +429,83 @@ RCT_STRUCT_CONVERTER(CGAffineTransform, (@[@"a", @"b", @"c", @"d", @"tx", @"ty"]
|
|||
return [self UIColor:json].CGColor;
|
||||
}
|
||||
|
||||
+ (CAKeyframeAnimation *)GIF:(id)json
|
||||
{
|
||||
CGImageSourceRef imageSource;
|
||||
if ([json isKindOfClass:[NSString class]]) {
|
||||
NSString *path = json;
|
||||
if (path.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSURL *fileURL = [path isAbsolutePath] ? [NSURL fileURLWithPath:path] : [[NSBundle mainBundle] URLForResource:path withExtension:nil];
|
||||
imageSource = CGImageSourceCreateWithURL((CFURLRef)fileURL, NULL);
|
||||
} else if ([json isKindOfClass:[NSData class]]) {
|
||||
NSData *data = json;
|
||||
if (data.length == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
imageSource = CGImageSourceCreateWithData((CFDataRef)data, NULL);
|
||||
}
|
||||
|
||||
if (!UTTypeConformsTo(CGImageSourceGetType(imageSource), kUTTypeGIF)) {
|
||||
CFRelease(imageSource);
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(imageSource, NULL);
|
||||
NSUInteger loopCount = [properties[(id)kCGImagePropertyGIFDictionary][(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue];
|
||||
|
||||
size_t imageCount = CGImageSourceGetCount(imageSource);
|
||||
NSTimeInterval duration = 0;
|
||||
NSMutableArray *delays = [NSMutableArray arrayWithCapacity:imageCount];
|
||||
NSMutableArray *images = [NSMutableArray arrayWithCapacity:imageCount];
|
||||
for (size_t i = 0; i < imageCount; i++) {
|
||||
CGImageRef image = CGImageSourceCreateImageAtIndex(imageSource, i, NULL);
|
||||
NSDictionary *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSource, i, NULL);
|
||||
NSDictionary *frameGIFProperties = frameProperties[(id)kCGImagePropertyGIFDictionary];
|
||||
|
||||
const NSTimeInterval kDelayTimeIntervalDefault = 0.1;
|
||||
NSNumber *delayTime = frameGIFProperties[(id)kCGImagePropertyGIFUnclampedDelayTime] ?: frameGIFProperties[(id)kCGImagePropertyGIFDelayTime];
|
||||
if (delayTime == nil) {
|
||||
if (i == 0) {
|
||||
delayTime = @(kDelayTimeIntervalDefault);
|
||||
} else {
|
||||
delayTime = delays[i - 1];
|
||||
}
|
||||
}
|
||||
|
||||
const NSTimeInterval kDelayTimeIntervalMinimum = 0.02;
|
||||
if (delayTime.floatValue < (float)kDelayTimeIntervalMinimum - FLT_EPSILON) {
|
||||
delayTime = @(kDelayTimeIntervalDefault);
|
||||
}
|
||||
|
||||
duration += delayTime.doubleValue;
|
||||
delays[i] = delayTime;
|
||||
images[i] = (__bridge_transfer id)image;
|
||||
}
|
||||
|
||||
CFRelease(imageSource);
|
||||
|
||||
NSMutableArray *keyTimes = [NSMutableArray arrayWithCapacity:delays.count];
|
||||
NSTimeInterval runningDuration = 0;
|
||||
for (NSNumber *delayNumber in delays) {
|
||||
[keyTimes addObject:@(runningDuration / duration)];
|
||||
runningDuration += delayNumber.doubleValue;
|
||||
}
|
||||
|
||||
[keyTimes addObject:@1.0];
|
||||
|
||||
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
|
||||
animation.calculationMode = kCAAnimationDiscrete;
|
||||
animation.repeatCount = loopCount == 0 ? HUGE_VALF : loopCount;
|
||||
animation.keyTimes = keyTimes;
|
||||
animation.values = images;
|
||||
animation.duration = duration;
|
||||
return animation;
|
||||
}
|
||||
|
||||
+ (UIImage *)UIImage:(id)json
|
||||
{
|
||||
if (![json isKindOfClass:[NSString class]]) {
|
||||
|
|
|
@ -33,9 +33,11 @@ typedef NS_ENUM(NSInteger, RCTScrollEventType) {
|
|||
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
||||
|
||||
/**
|
||||
* Send an arbitrary event type
|
||||
* Send a named event. For most purposes, use the an
|
||||
* event type of RCTEventTypeDefault, the other types
|
||||
* are used internally by the React framework.
|
||||
*/
|
||||
- (void)sendRawEventWithType:(NSString *)eventType body:(NSDictionary *)body;
|
||||
- (void)sendEventWithName:(NSString *)name body:(NSDictionary *)body;
|
||||
|
||||
/**
|
||||
* Send an array of touch events
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#import "RCTEventDispatcher.h"
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTModuleIDs.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
@implementation RCTEventDispatcher
|
||||
|
@ -19,39 +18,13 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)touchEvents
|
||||
- (void)sendEventWithName:(NSString *)name body:(NSDictionary *)body
|
||||
{
|
||||
static NSArray *events;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
events = @[
|
||||
@"topTouchStart",
|
||||
@"topTouchMove",
|
||||
@"topTouchEnd",
|
||||
@"topTouchCancel",
|
||||
];
|
||||
});
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
- (void)sendRawEventWithType:(NSString *)eventType body:(NSDictionary *)body
|
||||
{
|
||||
static NSSet *touchEvents;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
touchEvents = [NSSet setWithArray:[self touchEvents]];
|
||||
});
|
||||
|
||||
RCTAssert(![touchEvents containsObject:eventType], @"Touch events must be"
|
||||
"sent via the sendTouchEventWithOrderedTouches: method, not sendRawEventWithType:");
|
||||
|
||||
RCTAssert([body[@"target"] isKindOfClass:[NSNumber class]],
|
||||
@"Event body dictionary must include a 'target' property containing a react tag");
|
||||
|
||||
[_bridge enqueueJSCall:RCTModuleIDReactIOSEventEmitter
|
||||
methodID:RCTEventEmitterReceiveEvent
|
||||
args:@[body[@"target"], eventType, body]];
|
||||
[_bridge enqueueJSCall:@"RCTEventEmitter.receiveEvent"
|
||||
args:@[body[@"target"], name, body]];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,30 +42,32 @@
|
|||
touches:(NSArray *)touches
|
||||
changedIndexes:(NSArray *)changedIndexes
|
||||
{
|
||||
static NSString *events[] = {
|
||||
@"topTouchStart",
|
||||
@"topTouchMove",
|
||||
@"topTouchEnd",
|
||||
@"topTouchCancel",
|
||||
};
|
||||
|
||||
RCTAssert(touches.count, @"No touches in touchEventArgsForOrderedTouches");
|
||||
|
||||
[_bridge enqueueJSCall:RCTModuleIDReactIOSEventEmitter
|
||||
methodID:RCTEventEmitterReceiveTouches
|
||||
args:@[[self touchEvents][type], touches, changedIndexes]];
|
||||
[_bridge enqueueJSCall:@"RCTEventEmitter.receiveTouches"
|
||||
args:@[events[type], touches, changedIndexes]];
|
||||
}
|
||||
|
||||
- (void)sendTextEventWithType:(RCTTextEventType)type
|
||||
reactTag:(NSNumber *)reactTag
|
||||
text:(NSString *)text
|
||||
{
|
||||
static NSArray *events;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
events = @[
|
||||
static NSString *events[] = {
|
||||
@"topFocus",
|
||||
@"topBlur",
|
||||
@"topChange",
|
||||
@"topSubmitEditing",
|
||||
@"topEndEditing",
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
[self sendRawEventWithType:events[type] body:@{
|
||||
[self sendEventWithName:events[type] body:@{
|
||||
@"text": text,
|
||||
@"target": reactTag
|
||||
}];
|
||||
|
@ -111,18 +86,14 @@
|
|||
scrollView:(UIScrollView *)scrollView
|
||||
userData:(NSDictionary *)userData
|
||||
{
|
||||
static NSArray *events;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
events = @[
|
||||
static NSString *events[] = {
|
||||
@"topScrollBeginDrag",
|
||||
@"topScroll",
|
||||
@"topScrollEndDrag",
|
||||
@"topMomentumScrollBegin",
|
||||
@"topMomentumScrollEnd",
|
||||
@"topScrollAnimationEnd",
|
||||
];
|
||||
});
|
||||
};
|
||||
|
||||
NSDictionary *body = @{
|
||||
@"contentOffset": @{
|
||||
|
@ -147,7 +118,7 @@
|
|||
body = mutableBody;
|
||||
}
|
||||
|
||||
[self sendRawEventWithType:events[type] body:body];
|
||||
[self sendEventWithName:events[type] body:body];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -26,6 +26,7 @@ extern NSString *RCTExportedModuleNameAtSortedIndex(NSUInteger index);
|
|||
extern NSDictionary *RCTExportedMethodsByModule(void);
|
||||
|
||||
extern BOOL RCTSetProperty(id target, NSString *keypath, id value);
|
||||
extern BOOL RCTCopyProperty(id target, id source, NSString *keypath);
|
||||
extern BOOL RCTCallSetter(id target, SEL setter, id value);
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
|
@ -66,9 +67,22 @@ _RCTExportSectionName))) static const RCTExportEntry __rct_export_entry__ = { __
|
|||
|
||||
/**
|
||||
* Injects constants into JS. These constants are made accessible via
|
||||
* NativeModules.moduleName.X.
|
||||
* NativeModules.moduleName.X. Note that this method is not inherited when you
|
||||
* subclass a module, and you should not call [super constantsToExport] when
|
||||
* implementing it.
|
||||
*/
|
||||
- (NSDictionary *)constantsToExport;
|
||||
+ (NSDictionary *)constantsToExport;
|
||||
|
||||
/**
|
||||
* An array of JavaScript methods that the module will call via the
|
||||
* -[RCTBridge enqueueJSCall:args:] method. Each method should be specified
|
||||
* as a string of the form "JSModuleName.jsMethodName". Attempting to call a
|
||||
* method that has not been registered will result in an error. If a method
|
||||
* has already been regsistered by another module, it is not necessary to
|
||||
* register it again, but it is good pratice. Registering the same method
|
||||
* more than once is silently ignored and will not result in an error.
|
||||
*/
|
||||
+ (NSArray *)JSMethods;
|
||||
|
||||
/**
|
||||
* Notifies the module that a batch of JS method invocations has just completed.
|
||||
|
@ -84,9 +98,18 @@ _RCTExportSectionName))) static const RCTExportEntry __rct_export_entry__ = { __
|
|||
@protocol RCTNativeViewModule <NSObject>
|
||||
|
||||
/**
|
||||
* This method instantiates a native view to be managed by the module.
|
||||
* Designated initializer for view modules. The event dispatched can either be
|
||||
* used directly by the module, or passed on to instantiated views for event handling.
|
||||
*/
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
/**
|
||||
* This method instantiates a native view to be managed by the module. The method
|
||||
* will be called many times, and should return a fresh instance each time. The
|
||||
* view module MUST NOT cache the returned view and return the same instance
|
||||
* for subsequent calls.
|
||||
*/
|
||||
- (UIView *)view;
|
||||
|
||||
@optional
|
||||
|
||||
|
@ -98,7 +121,8 @@ _RCTExportSectionName))) static const RCTExportEntry __rct_export_entry__ = { __
|
|||
|
||||
/**
|
||||
* This method instantiates a shadow view to be managed by the module. If omitted,
|
||||
* an ordinary RCTShadowView instance will be created.
|
||||
* an ordinary RCTShadowView instance will be created. As with the -view method,
|
||||
* the -shadowView method should return a fresh instance each time it is called.
|
||||
*/
|
||||
- (RCTShadowView *)shadowView;
|
||||
|
||||
|
@ -164,8 +188,11 @@ RCT_REMAP_VIEW_PROPERTY(name, name)
|
|||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Note that this method is not inherited when you subclass a view module, and
|
||||
* you should not call [super customBubblingEventTypes] when implementing it.
|
||||
*/
|
||||
- (NSDictionary *)customBubblingEventTypes;
|
||||
+ (NSDictionary *)customBubblingEventTypes;
|
||||
|
||||
/**
|
||||
* Returns a dictionary of config data passed to JS that defines eligible events
|
||||
|
@ -177,14 +204,19 @@ RCT_REMAP_VIEW_PROPERTY(name, name)
|
|||
* @"registrationName": @"onTwirl"
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Note that this method is not inherited when you subclass a view module, and
|
||||
* you should not call [super customDirectEventTypes] when implementing it.
|
||||
*/
|
||||
- (NSDictionary *)customDirectEventTypes;
|
||||
+ (NSDictionary *)customDirectEventTypes;
|
||||
|
||||
/**
|
||||
* Injects constants into JS. These constants are made accessible via
|
||||
* NativeModules.moduleName.X.
|
||||
* NativeModules.moduleName.X. Note that this method is not inherited when you
|
||||
* subclass a view module, and you should not call [super constantsToExport]
|
||||
* when implementing it.
|
||||
*/
|
||||
- (NSDictionary *)constantsToExport;
|
||||
+ (NSDictionary *)constantsToExport;
|
||||
|
||||
/**
|
||||
* To deprecate, hopefully
|
||||
|
|
|
@ -349,6 +349,36 @@ BOOL RCTSetProperty(id target, NSString *keypath, id value)
|
|||
return YES;
|
||||
}
|
||||
|
||||
BOOL RCTCopyProperty(id target, id source, NSString *keypath)
|
||||
{
|
||||
// Split keypath
|
||||
NSArray *parts = [keypath componentsSeparatedByString:@"."];
|
||||
NSString *key = [parts lastObject];
|
||||
for (NSUInteger i = 0; i < parts.count - 1; i++) {
|
||||
source = [source valueForKey:parts[i]];
|
||||
target = [target valueForKey:parts[i]];
|
||||
if (!source || !target) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// Check class for property definition
|
||||
if (!class_getProperty([source class], [key UTF8String])) {
|
||||
// Check if setter exists
|
||||
SEL setter = NSSelectorFromString([NSString stringWithFormat:@"set%@%@:",
|
||||
[[key substringToIndex:1] uppercaseString],
|
||||
[key substringFromIndex:1]]);
|
||||
|
||||
if (![source respondsToSelector:setter]
|
||||
|| ![target respondsToSelector:setter]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
[target setValue:[source valueForKey:key] forKey:key];
|
||||
return YES;
|
||||
}
|
||||
|
||||
BOOL RCTCallSetter(id target, SEL setter, id value)
|
||||
{
|
||||
// Get property name
|
||||
|
|
|
@ -2,12 +2,16 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef void (^RCTDataDownloadBlock)(NSData *data, NSError *error);
|
||||
typedef void (^RCTImageDownloadBlock)(UIImage *image, NSError *error);
|
||||
|
||||
@interface RCTImageDownloader : NSObject
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
|
||||
- (id)downloadDataForURL:(NSURL *)url
|
||||
block:(RCTDataDownloadBlock)block;
|
||||
|
||||
- (id)downloadImageForURL:(NSURL *)url
|
||||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
|
|
|
@ -18,6 +18,20 @@
|
|||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (id)downloadDataForURL:(NSURL *)url
|
||||
block:(RCTDataDownloadBlock)block
|
||||
{
|
||||
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
||||
// Dispatch back to main thread
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
block(data, error);
|
||||
});
|
||||
}];
|
||||
|
||||
[task resume];
|
||||
return task;
|
||||
}
|
||||
|
||||
- (id)downloadImageForURL:(NSURL *)url
|
||||
size:(CGSize)size
|
||||
scale:(CGFloat)scale
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* All of this will be replaced with an auto-generated bridge.
|
||||
*/
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTJSModuleIDs) {
|
||||
RCTModuleIDReactIOSEventEmitter,
|
||||
RCTModuleIDJSTimers, // JS timer tracking module
|
||||
RCTModuleIDReactIOS,
|
||||
RCTModuleIDBundler,
|
||||
RCTModuleIDDimensions,
|
||||
RCTModuleIDDeviceEventEmitter,
|
||||
RCTModuleIDNativeAppEventEmitter,
|
||||
};
|
||||
|
||||
/**
|
||||
* JS module `RCTIOSEventEmitter`.
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, RCTEventEmitterRemoteMethodIDs) {
|
||||
RCTEventEmitterReceiveEvent = 0,
|
||||
RCTEventEmitterReceiveTouches
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTKeyCode) {
|
||||
RCTKeyCodeBackspace = 8,
|
||||
RCTKeyCodeReturn = 13,
|
||||
};
|
||||
|
||||
/**
|
||||
* JS timer tracking module.
|
||||
*/
|
||||
typedef NS_ENUM(NSUInteger, RCTJSTimersMethodIDs) {
|
||||
RCTJSTimersCallTimers = 0
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTReactIOSMethodIDs) {
|
||||
RCTReactIOSUnmountComponentAtNodeAndRemoveContainer = 0,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTBundlerMethodIDs) {
|
||||
RCTBundlerRunApplication = 0
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTDimensionsMethodIDs) {
|
||||
RCTDimensionsSet = 0
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RCTDeviceEventEmitterMethodIDs) {
|
||||
RCTDeviceEventEmitterEmit = 0
|
||||
};
|
||||
|
||||
@interface RCTModuleIDs : NSObject
|
||||
|
||||
+ (NSDictionary *)config;
|
||||
|
||||
@end
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTModuleIDs.h"
|
||||
|
||||
@implementation RCTModuleIDs
|
||||
|
||||
/**
|
||||
* Configures invocations from IOS -> JS. Simply passes the name of the key in
|
||||
* the configuration object `require('ReactIOSEventEmitter')`.
|
||||
*/
|
||||
+ (NSDictionary *)config
|
||||
{
|
||||
return @{
|
||||
@"Dimensions": @{
|
||||
@"moduleID": @(RCTModuleIDDimensions),
|
||||
@"methods": @{
|
||||
@"set": @{
|
||||
@"methodID": @(RCTDimensionsSet),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"RCTDeviceEventEmitter": @{
|
||||
@"moduleID": @(RCTModuleIDDeviceEventEmitter),
|
||||
@"methods": @{
|
||||
@"emit": @{
|
||||
@"methodID": @(RCTDeviceEventEmitterEmit),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"RCTEventEmitter": @{
|
||||
@"moduleID": @(RCTModuleIDReactIOSEventEmitter),
|
||||
@"methods": @{
|
||||
@"receiveEvent": @{
|
||||
@"methodID": @(RCTEventEmitterReceiveEvent),
|
||||
@"type": @"local"
|
||||
},
|
||||
@"receiveTouches": @{
|
||||
@"methodID": @(RCTEventEmitterReceiveTouches),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"RCTNativeAppEventEmitter": @{
|
||||
@"moduleID": @(RCTModuleIDNativeAppEventEmitter),
|
||||
@"methods": @{
|
||||
@"emit": @{
|
||||
@"methodID": @(RCTDeviceEventEmitterEmit),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"RCTJSTimers": @{
|
||||
@"moduleID": @(RCTModuleIDJSTimers),
|
||||
@"methods": @{
|
||||
// Last argument is the callback.
|
||||
@"callTimers": @{
|
||||
@"methodID": @(RCTJSTimersCallTimers),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"ReactIOS": @{
|
||||
@"moduleID": @(RCTModuleIDReactIOS),
|
||||
@"methods": @{
|
||||
@"unmountComponentAtNodeAndRemoveContainer": @{
|
||||
@"methodID": @(RCTReactIOSUnmountComponentAtNodeAndRemoveContainer),
|
||||
@"type": @"local"
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@"Bundler": @{
|
||||
@"moduleID": @(RCTModuleIDBundler),
|
||||
@"methods": @{
|
||||
@"runApplication": @{
|
||||
@"methodID": @(RCTBundlerRunApplication),
|
||||
@"type": @"local"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -6,11 +6,11 @@
|
|||
#import "RCTContextExecutor.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTJavaScriptAppEngine.h"
|
||||
#import "RCTModuleIDs.h"
|
||||
#import "RCTTouchHandler.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTViewManager.h"
|
||||
#import "RCTWebViewExecutor.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
#import "RCTKeyCommands.h"
|
||||
|
||||
|
@ -23,6 +23,8 @@ NSString *const RCTRootViewReloadNotification = @"RCTRootViewReloadNotification"
|
|||
RCTTouchHandler *_touchHandler;
|
||||
}
|
||||
|
||||
static BOOL _useWebExec;
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
|
||||
|
@ -34,6 +36,13 @@ NSString *const RCTRootViewReloadNotification = @"RCTRootViewReloadNotification"
|
|||
action:^(UIKeyCommand *command) {
|
||||
[self reloadAll];
|
||||
}];
|
||||
// Cmd-D reloads using the web view executor, allows attaching from Safari dev tools.
|
||||
[[RCTKeyCommands sharedInstance] registerKeyCommandWithInput:@"d"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:^(UIKeyCommand *command) {
|
||||
_useWebExec = YES;
|
||||
[self reloadAll];
|
||||
}];
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -98,8 +107,8 @@ NSString *const RCTRootViewReloadNotification = @"RCTRootViewReloadNotification"
|
|||
@"rootTag": self.reactTag ?: @0,
|
||||
@"initialProps": self.initialProperties ?: @{},
|
||||
};
|
||||
[_bridge enqueueJSCall:RCTModuleIDBundler
|
||||
methodID:RCTBundlerRunApplication
|
||||
|
||||
[_bridge enqueueJSCall:@"Bundler.runApplication"
|
||||
args:@[moduleName, appParameters]];
|
||||
}
|
||||
}
|
||||
|
@ -123,9 +132,13 @@ NSString *const RCTRootViewReloadNotification = @"RCTRootViewReloadNotification"
|
|||
[_executor invalidate];
|
||||
[_bridge invalidate];
|
||||
|
||||
if (!_useWebExec) {
|
||||
_executor = [[RCTContextExecutor alloc] init];
|
||||
_bridge = [[RCTBridge alloc] initWithJavaScriptExecutor:_executor
|
||||
javaScriptModulesConfig:[RCTModuleIDs config]];
|
||||
} else {
|
||||
_executor = [[RCTWebViewExecutor alloc] init];
|
||||
}
|
||||
|
||||
_bridge = [[RCTBridge alloc] initWithJavaScriptExecutor:_executor];
|
||||
|
||||
_appEngine = [[RCTJavaScriptAppEngine alloc] initWithBridge:_bridge];
|
||||
_touchHandler = [[RCTTouchHandler alloc] initWithEventDispatcher:_bridge.eventDispatcher rootView:self];
|
||||
|
@ -165,22 +178,4 @@ NSString *const RCTRootViewReloadNotification = @"RCTRootViewReloadNotification"
|
|||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRootViewReloadNotification object:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Key commands
|
||||
|
||||
- (NSArray *)keyCommands
|
||||
{
|
||||
return @[
|
||||
|
||||
// Reload
|
||||
[UIKeyCommand keyCommandWithInput:@"r"
|
||||
modifierFlags:UIKeyModifierCommand
|
||||
action:@selector(reload)]
|
||||
];
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
|
||||
@interface RCTSparseArray : NSObject <NSCopying>
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithCapacity:(NSUInteger)capacity;
|
||||
- (instancetype)initWithSparseArray:(RCTSparseArray *)sparseArray;
|
||||
- (instancetype)initWithCapacity:(NSUInteger)capacity NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithSparseArray:(RCTSparseArray *)sparseArray NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (instancetype)sparseArray;
|
||||
+ (instancetype)sparseArrayWithCapacity:(NSUInteger)capacity;
|
||||
|
|
|
@ -28,14 +28,6 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithStorage:(NSDictionary *)storage
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_storage = [storage copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)sparseArray
|
||||
{
|
||||
return [[self alloc] init];
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#import "RCTUtils.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
// TODO: this class behaves a lot like a module, and could be implemented as a
|
||||
// module if we were to assume that modules and RootViews had a 1:1 relationship
|
||||
|
||||
@implementation RCTTouchHandler
|
||||
{
|
||||
__weak UIView *_rootView;
|
||||
|
@ -27,11 +30,6 @@
|
|||
NSMutableArray *_touchViews;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithTarget:(id)target action:(SEL)action
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
|
|
|
@ -20,8 +20,9 @@ id RCTJSONParse(NSString *jsonString, NSError **error);
|
|||
// Get MD5 hash of a string
|
||||
NSString *RCTMD5Hash(NSString *string);
|
||||
|
||||
// Get screen scale in a thread-safe way
|
||||
// Get screen metrics in a thread-safe way
|
||||
CGFloat RCTScreenScale(void);
|
||||
CGSize RCTScreenSize(void);
|
||||
|
||||
// Round float coordinates to nearest whole screen pixel (not point)
|
||||
CGFloat RCTRoundPixelValue(CGFloat value);
|
||||
|
@ -34,3 +35,7 @@ NSTimeInterval RCTTGetAbsoluteTime(void);
|
|||
// Method swizzling
|
||||
void RCTSwapClassMethods(Class cls, SEL original, SEL replacement);
|
||||
void RCTSwapInstanceMethods(Class cls, SEL original, SEL replacement);
|
||||
|
||||
// Module subclass support
|
||||
BOOL RCTClassOverridesClassMethod(Class cls, SEL selector);
|
||||
BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector);
|
||||
|
|
|
@ -35,7 +35,7 @@ NSString *RCTMD5Hash(NSString *string)
|
|||
|
||||
CGFloat RCTScreenScale()
|
||||
{
|
||||
static CGFloat scale = -1;
|
||||
static CGFloat scale;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
if (![NSThread isMainThread]) {
|
||||
|
@ -50,6 +50,23 @@ CGFloat RCTScreenScale()
|
|||
return scale;
|
||||
}
|
||||
|
||||
CGSize RCTScreenSize()
|
||||
{
|
||||
static CGSize size;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
if (![NSThread isMainThread]) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
size = [UIScreen mainScreen].bounds.size;
|
||||
});
|
||||
} else {
|
||||
size = [UIScreen mainScreen].bounds.size;
|
||||
}
|
||||
});
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
CGFloat RCTRoundPixelValue(CGFloat value)
|
||||
{
|
||||
CGFloat scale = RCTScreenScale();
|
||||
|
@ -120,3 +137,24 @@ void RCTSwapInstanceMethods(Class cls, SEL original, SEL replacement)
|
|||
method_exchangeImplementations(originalMethod, replacementMethod);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL RCTClassOverridesClassMethod(Class cls, SEL selector)
|
||||
{
|
||||
return RCTClassOverridesInstanceMethod(object_getClass(cls), selector);
|
||||
}
|
||||
|
||||
BOOL RCTClassOverridesInstanceMethod(Class cls, SEL selector)
|
||||
{
|
||||
unsigned int numberOfMethods;
|
||||
Method *methods = class_copyMethodList(cls, &numberOfMethods);
|
||||
for (unsigned int i = 0; i < numberOfMethods; i++)
|
||||
{
|
||||
if (method_getName(methods[i]) == selector)
|
||||
{
|
||||
free(methods);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||
return self;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
return [self initWithWebView:[[UIWebView alloc] init]];
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _webView != nil;
|
||||
|
@ -98,7 +103,13 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||
sourceURL:(NSURL *)url
|
||||
onComplete:(RCTJavaScriptCompleteBlock)onComplete
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
if (![NSThread isMainThread]) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[self executeApplicationScript:script sourceURL:url onComplete:onComplete];
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
RCTAssert(onComplete != nil, @"");
|
||||
_onApplicationScriptLoaded = onComplete;
|
||||
|
||||
|
@ -137,26 +148,12 @@ static void RCTReportError(RCTJavaScriptCallback callback, NSString *fmt, ...)
|
|||
*/
|
||||
- (void)executeBlockOnJavaScriptQueue:(dispatch_block_t)block
|
||||
{
|
||||
if (![NSThread isMainThread]) {
|
||||
[self performSelectorOnMainThread:@selector(executeBlockOnJavaScriptQueue:)
|
||||
withObject:block
|
||||
waitUntilDone:YES];
|
||||
} else {
|
||||
[self performSelector:@selector(_onMainThreadExecuteBlockAfterDelay:)
|
||||
withObject:block afterDelay:0.001 // This can't be zero!
|
||||
inModes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]];
|
||||
}
|
||||
}
|
||||
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC);
|
||||
|
||||
/**
|
||||
* This timing delay is needed to avoid crashes in WebKit when setting a
|
||||
* breakpoint or `debugger` statement and debugging via the remote Safari
|
||||
* inspector.
|
||||
*/
|
||||
- (void)_onMainThreadExecuteBlockAfterDelay:(dispatch_block_t)block
|
||||
{
|
||||
dispatch_after(when, dispatch_get_main_queue(), ^{
|
||||
RCTAssertMainThread();
|
||||
block();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTModuleIDs.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
|
@ -55,6 +54,11 @@
|
|||
id _updateTimer;
|
||||
}
|
||||
|
||||
+ (NSArray *)JSMethods
|
||||
{
|
||||
return @[@"RCTJSTimers.callTimers"];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
|
@ -143,7 +147,7 @@
|
|||
|
||||
// call timers that need to be called
|
||||
if ([timersToCall count] > 0) {
|
||||
[_bridge enqueueJSCall:RCTModuleIDJSTimers methodID:RCTJSTimersCallTimers args:@[timersToCall]];
|
||||
[_bridge enqueueJSCall:@"RCTJSTimers.callTimers" args:@[timersToCall]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,14 +159,14 @@
|
|||
* Date.now() from JS and then subtracting that from the current time here.
|
||||
*/
|
||||
- (void)createTimer:(NSNumber *)callbackID
|
||||
duration:(NSNumber *)jsDuration
|
||||
jsSchedulingTime:(NSNumber *)jsSchedulingTime
|
||||
repeats:(NSNumber *)repeats
|
||||
duration:(double)jsDuration
|
||||
jsSchedulingTime:(double)jsSchedulingTime
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
NSTimeInterval interval = jsDuration.doubleValue / 1000;
|
||||
NSTimeInterval jsCreationTimeSinceUnixEpoch = jsSchedulingTime.doubleValue / 1000;
|
||||
NSTimeInterval interval = jsDuration / 1000;
|
||||
NSTimeInterval jsCreationTimeSinceUnixEpoch = jsSchedulingTime / 1000;
|
||||
NSTimeInterval currentTimeSinceUnixEpoch = [[NSDate date] timeIntervalSince1970];
|
||||
NSTimeInterval jsSchedulingOverhead = currentTimeSinceUnixEpoch - jsCreationTimeSinceUnixEpoch;
|
||||
if (jsSchedulingOverhead < 0) {
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
@protocol RCTScrollableProtocol;
|
||||
@protocol RCTViewNodeProtocol;
|
||||
|
||||
@interface RCTUIManager : NSObject <RCTInvalidating, RCTNativeModule>
|
||||
@interface RCTUIManager : NSObject <RCTNativeModule, RCTInvalidating>
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge;
|
||||
|
||||
|
|
|
@ -34,26 +34,6 @@ static void RCTTraverseViewNodes(id<RCTViewNodeProtocol> view, react_view_node_b
|
|||
}
|
||||
}
|
||||
|
||||
static NSString *RCTModuleName(Class moduleClass)
|
||||
{
|
||||
if ([moduleClass respondsToSelector:@selector(moduleName)]) {
|
||||
|
||||
return [moduleClass moduleName];
|
||||
|
||||
} else {
|
||||
|
||||
// Default implementation, works in most cases
|
||||
NSString *className = NSStringFromClass(moduleClass);
|
||||
if ([className hasPrefix:@"RCTUI"]) {
|
||||
className = [className substringFromIndex:@"RCT".length];
|
||||
}
|
||||
if ([className hasSuffix:@"Manager"]) {
|
||||
className = [className substringToIndex:className.length - @"Manager".length];
|
||||
}
|
||||
return className;
|
||||
}
|
||||
}
|
||||
|
||||
static NSDictionary *RCTViewModuleClasses(void)
|
||||
{
|
||||
static NSMutableDictionary *modules;
|
||||
|
@ -78,7 +58,7 @@ static NSDictionary *RCTViewModuleClasses(void)
|
|||
}
|
||||
|
||||
// Get module name
|
||||
NSString *moduleName = RCTModuleName(cls);
|
||||
NSString *moduleName = [cls respondsToSelector:@selector(moduleName)] ? [cls moduleName] : NSStringFromClass(cls);
|
||||
|
||||
// Check module name is unique
|
||||
id existingClass = modules[moduleName];
|
||||
|
@ -131,7 +111,7 @@ static NSDictionary *RCTViewModuleClasses(void)
|
|||
// Instantiate view managers
|
||||
NSMutableDictionary *viewManagers = [[NSMutableDictionary alloc] init];
|
||||
[RCTViewModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *moduleName, Class moduleClass, BOOL *stop) {
|
||||
viewManagers[moduleName] = [[moduleClass alloc] init];
|
||||
viewManagers[moduleName] = [[moduleClass alloc] initWithEventDispatcher:_bridge.eventDispatcher];
|
||||
}];
|
||||
_viewManagers = viewManagers;
|
||||
|
||||
|
@ -535,11 +515,6 @@ static NSDictionary *RCTViewModuleClasses(void)
|
|||
}
|
||||
}
|
||||
|
||||
- (UIView *)viewForViewManager:(id <RCTNativeViewModule>)manager
|
||||
{
|
||||
return [manager viewWithEventDispatcher:_bridge.eventDispatcher];
|
||||
}
|
||||
|
||||
static BOOL RCTCallPropertySetter(SEL setter, id value, id view, id defaultView, id <RCTNativeViewModule>manager)
|
||||
{
|
||||
// TODO: cache respondsToSelector tests
|
||||
|
@ -581,7 +556,9 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
|
||||
if (obj == [NSNull null]) {
|
||||
// Copy property from default view to current
|
||||
RCTSetProperty(shadowView, key, [defaultView valueForKey:key]);
|
||||
// Note: not just doing `[defaultView valueForKey:key]`, the
|
||||
// key may not exist, in which case we'd get an exception.
|
||||
RCTCopyProperty(shadowView, defaultView, key);
|
||||
} else {
|
||||
RCTSetProperty(shadowView, key, obj);
|
||||
}
|
||||
|
@ -619,10 +596,10 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
// Note the default is setup after the props are read for the first time ever
|
||||
// for this className - this is ok because we only use the default for restoring
|
||||
// defaults, which never happens on first creation.
|
||||
uiManager->_defaultViews[moduleName] = [uiManager viewForViewManager:manager];
|
||||
uiManager->_defaultViews[moduleName] = [manager view];
|
||||
}
|
||||
|
||||
UIView *view = [uiManager viewForViewManager:manager];
|
||||
UIView *view = [manager view];
|
||||
if (view) {
|
||||
// Set required properties
|
||||
view.reactTag = reactTag;
|
||||
|
@ -1013,7 +990,7 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
}];
|
||||
}
|
||||
|
||||
- (NSDictionary *)allBubblingEventTypesConfigs
|
||||
+ (NSDictionary *)allBubblingEventTypesConfigs
|
||||
{
|
||||
NSMutableDictionary *customBubblingEventTypesConfigs = [@{
|
||||
// Bubble dispatched events
|
||||
|
@ -1103,20 +1080,20 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
},
|
||||
} mutableCopy];
|
||||
|
||||
for (id <RCTNativeViewModule> viewManager in _viewManagers.allValues) {
|
||||
NSDictionary *bubblingEvents = [viewManager respondsToSelector:@selector(customBubblingEventTypes)]? [viewManager customBubblingEventTypes] : nil;
|
||||
if (bubblingEvents) {
|
||||
for (NSString *eventName in bubblingEvents) {
|
||||
RCTCAssert(!customBubblingEventTypesConfigs[eventName], @"Event %@ registered multiple times.", eventName);
|
||||
}
|
||||
[customBubblingEventTypesConfigs addEntriesFromDictionary:bubblingEvents];
|
||||
[RCTViewModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
if (RCTClassOverridesClassMethod(cls, @selector(customBubblingEventTypes))) {
|
||||
NSDictionary *eventTypes = [cls customBubblingEventTypes];
|
||||
for (NSString *eventName in eventTypes) {
|
||||
RCTCAssert(!customBubblingEventTypesConfigs[eventName], @"Event '%@' registered multiple times.", eventName);
|
||||
}
|
||||
[customBubblingEventTypesConfigs addEntriesFromDictionary:eventTypes];
|
||||
}
|
||||
}];
|
||||
|
||||
return customBubblingEventTypesConfigs;
|
||||
}
|
||||
|
||||
- (NSDictionary *)allDirectEventTypesConfigs
|
||||
+ (NSDictionary *)allDirectEventTypesConfigs
|
||||
{
|
||||
NSMutableDictionary *customDirectEventTypes = [@{
|
||||
@"topScrollBeginDrag": @{
|
||||
|
@ -1154,22 +1131,21 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
},
|
||||
} mutableCopy];
|
||||
|
||||
for (id <RCTNativeViewModule> viewManager in _viewManagers.allValues) {
|
||||
NSDictionary *bubblingEvents = [viewManager respondsToSelector:@selector(customDirectEventTypes)] ? [viewManager customDirectEventTypes] : nil;
|
||||
if (bubblingEvents) {
|
||||
for (NSString *eventName in bubblingEvents) {
|
||||
RCTCAssert(!customDirectEventTypes[eventName], @"Event %@ registered multiple times.", eventName);
|
||||
}
|
||||
[customDirectEventTypes addEntriesFromDictionary:bubblingEvents];
|
||||
[RCTViewModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
if (RCTClassOverridesClassMethod(cls, @selector(customDirectEventTypes))) {
|
||||
NSDictionary *eventTypes = [cls customDirectEventTypes];
|
||||
for (NSString *eventName in eventTypes) {
|
||||
RCTCAssert(!customDirectEventTypes[eventName], @"Event '%@' registered multiple times.", eventName);
|
||||
}
|
||||
[customDirectEventTypes addEntriesFromDictionary:eventTypes];
|
||||
}
|
||||
}];
|
||||
|
||||
return customDirectEventTypes;
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
+ (NSDictionary *)constantsToExport
|
||||
{
|
||||
UIScreen *screen = [UIScreen mainScreen];
|
||||
NSMutableDictionary *allJSConstants = [@{
|
||||
@"customBubblingEventTypes": [self allBubblingEventTypesConfigs],
|
||||
@"customDirectEventTypes": [self allDirectEventTypesConfigs],
|
||||
|
@ -1180,13 +1156,13 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
},
|
||||
@"Dimensions": @{
|
||||
@"window": @{
|
||||
@"width": @(screen.bounds.size.width),
|
||||
@"height": @(screen.bounds.size.height),
|
||||
@"scale": @(screen.scale),
|
||||
@"width": @(RCTScreenSize().width),
|
||||
@"height": @(RCTScreenSize().height),
|
||||
@"scale": @(RCTScreenScale()),
|
||||
},
|
||||
@"modalFullscreenView": @{
|
||||
@"width": @(screen.bounds.size.width),
|
||||
@"height": @(screen.bounds.size.height),
|
||||
@"width": @(RCTScreenSize().width),
|
||||
@"height": @(RCTScreenSize().width),
|
||||
},
|
||||
},
|
||||
@"StyleConstants": @{
|
||||
|
@ -1224,12 +1200,15 @@ static void RCTSetShadowViewProps(NSDictionary *props, RCTShadowView *shadowView
|
|||
},
|
||||
} mutableCopy];
|
||||
|
||||
[_viewManagers enumerateKeysAndObjectsUsingBlock:^(NSString *name, id <RCTNativeViewModule> viewManager, BOOL *stop) {
|
||||
NSDictionary *constants = [viewManager respondsToSelector:@selector(constantsToExport)] ? [viewManager constantsToExport] : nil;
|
||||
if (constants) {
|
||||
RCTAssert(allJSConstants[name] == nil , @"Cannot redefine constant namespace: %@", name);
|
||||
[RCTViewModuleClasses() enumerateKeysAndObjectsUsingBlock:^(NSString *name, Class cls, BOOL *stop) {
|
||||
// TODO: should these be inherited?
|
||||
NSDictionary *constants = RCTClassOverridesClassMethod(cls, @selector(constantsToExport)) ? [cls constantsToExport] : nil;
|
||||
if ([constants count]) {
|
||||
NSMutableDictionary *namespace = [NSMutableDictionary dictionaryWithDictionary:allJSConstants[name]];
|
||||
RCTAssert(namespace[@"Constants"] == nil , @"Cannot redefine Constants in namespace: %@", name);
|
||||
// add an additional 'Constants' namespace for each class
|
||||
allJSConstants[name] = @{@"Constants": constants};
|
||||
namespace[@"Constants"] = constants;
|
||||
allJSConstants[name] = [namespace copy];
|
||||
}
|
||||
}];
|
||||
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
83CBBA601A601EAA00E9B192 /* RCTBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA5F1A601EAA00E9B192 /* RCTBridge.m */; };
|
||||
83CBBA691A601EF300E9B192 /* RCTEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */; };
|
||||
83CBBA871A60202500E9B192 /* RCTJavaScriptAppEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA861A60202500E9B192 /* RCTJavaScriptAppEngine.m */; };
|
||||
83CBBA8B1A60204600E9B192 /* RCTModuleIDs.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA8A1A60204600E9B192 /* RCTModuleIDs.m */; };
|
||||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */; };
|
||||
83CBBACC1A6023D300E9B192 /* RCTConvert.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CBBACB1A6023D300E9B192 /* RCTConvert.m */; };
|
||||
83EEC2EE1A604AB200C39218 /* RCTModuleMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 83EEC2ED1A604AB200C39218 /* RCTModuleMethod.m */; };
|
||||
|
@ -162,8 +161,6 @@
|
|||
83CBBA661A601EF300E9B192 /* RCTEventDispatcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTEventDispatcher.m; sourceTree = "<group>"; };
|
||||
83CBBA851A60202500E9B192 /* RCTJavaScriptAppEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTJavaScriptAppEngine.h; sourceTree = "<group>"; };
|
||||
83CBBA861A60202500E9B192 /* RCTJavaScriptAppEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTJavaScriptAppEngine.m; sourceTree = "<group>"; };
|
||||
83CBBA891A60204600E9B192 /* RCTModuleIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTModuleIDs.h; sourceTree = "<group>"; };
|
||||
83CBBA8A1A60204600E9B192 /* RCTModuleIDs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTModuleIDs.m; sourceTree = "<group>"; };
|
||||
83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTouchHandler.h; sourceTree = "<group>"; };
|
||||
83CBBA971A6020BB00E9B192 /* RCTTouchHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTouchHandler.m; sourceTree = "<group>"; };
|
||||
83CBBACA1A6023D300E9B192 /* RCTConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTConvert.h; sourceTree = "<group>"; };
|
||||
|
@ -329,8 +326,6 @@
|
|||
83BEE46D1A6D19BC00B5863B /* RCTSparseArray.m */,
|
||||
83CBBA4D1A601E3B00E9B192 /* RCTLog.h */,
|
||||
83CBBA4E1A601E3B00E9B192 /* RCTLog.m */,
|
||||
83CBBA891A60204600E9B192 /* RCTModuleIDs.h */,
|
||||
83CBBA8A1A60204600E9B192 /* RCTModuleIDs.m */,
|
||||
83CBBA581A601E9000E9B192 /* RCTRedBox.h */,
|
||||
83CBBA591A601E9000E9B192 /* RCTRedBox.m */,
|
||||
83CBBA961A6020BB00E9B192 /* RCTTouchHandler.h */,
|
||||
|
@ -439,7 +434,6 @@
|
|||
13E067591A70F44B002CDEE1 /* UIView+ReactKit.m in Sources */,
|
||||
137029531A69923600575408 /* RCTImageDownloader.m in Sources */,
|
||||
83CBBA981A6020BB00E9B192 /* RCTTouchHandler.m in Sources */,
|
||||
83CBBA8B1A60204600E9B192 /* RCTModuleIDs.m in Sources */,
|
||||
83CBBA521A601E3B00E9B192 /* RCTLog.m in Sources */,
|
||||
13B080071A6947C200A75B9A /* RCTShadowRawText.m in Sources */,
|
||||
13B0801D1A69489C00A75B9A /* RCTNavItemManager.m in Sources */,
|
||||
|
@ -555,6 +549,7 @@
|
|||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
@ -564,6 +559,7 @@
|
|||
83CBBA411A601D0F00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
@implementation RCTNavItemManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTNavItem alloc] initWithFrame:CGRectZero];
|
||||
return [[RCTNavItem alloc] init];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(title)
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
@property (nonatomic, strong) UIView *reactNavSuperviewLink;
|
||||
@property (nonatomic, assign) NSInteger requestedTopOfStack;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
/**
|
||||
* Schedules a JavaScript navigation and prevents `UIKit` from navigating until
|
||||
|
|
|
@ -126,7 +126,17 @@ NSInteger kNeverProgressed = -10000;
|
|||
*/
|
||||
@implementation RCTNavigationController
|
||||
|
||||
- (instancetype)init
|
||||
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
@ -137,7 +147,7 @@ NSInteger kNeverProgressed = -10000;
|
|||
*/
|
||||
- (instancetype)initWithScrollCallback:(dispatch_block_t)callback
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
if ((self = [super initWithNibName:nil bundle:nil])) {
|
||||
_scrollCallback = callback;
|
||||
}
|
||||
return self;
|
||||
|
@ -265,11 +275,14 @@ NSInteger kNeverProgressed = -10000;
|
|||
|
||||
@implementation RCTNavigator
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame
|
||||
eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (id)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if ((self = [super initWithFrame:CGRectZero])) {
|
||||
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(reportNavigationProgress:)];
|
||||
_mostRecentProgress = kNeverProgressed;
|
||||
_dummyView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
@ -311,24 +324,15 @@ NSInteger kNeverProgressed = -10000;
|
|||
return;
|
||||
}
|
||||
_mostRecentProgress = nextProgress;
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavigationProgress"
|
||||
body:@{@"fromIndex": @(_currentlyTransitioningFrom),
|
||||
[_eventDispatcher sendEventWithName:@"topNavigationProgress" body:@{
|
||||
@"fromIndex": @(_currentlyTransitioningFrom),
|
||||
@"toIndex": @(_currentlyTransitioningTo),
|
||||
@"progress": @(nextProgress),
|
||||
@"target": self.reactTag}];
|
||||
@"target": self.reactTag
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
_navigationController.delegate = nil;
|
||||
|
@ -438,9 +442,10 @@ NSInteger kNeverProgressed = -10000;
|
|||
|
||||
- (void)handleTopOfStackChanged
|
||||
{
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavigateBack"
|
||||
body:@{@"target":self.reactTag,
|
||||
@"stackLength":@(_navigationController.viewControllers.count)}];
|
||||
[_eventDispatcher sendEventWithName:@"topNavigateBack" body:@{
|
||||
@"target":self.reactTag,
|
||||
@"stackLength":@(_navigationController.viewControllers.count)
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)dispatchFakeScrollEvent
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
@implementation RCTNavigatorManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTNavigator alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
return [[RCTNavigator alloc] initWithEventDispatcher:self.eventDispatcher];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(requestedTopOfStack)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#import "RCTImageDownloader.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTConvert.h"
|
||||
|
||||
@implementation RCTNetworkImageView
|
||||
{
|
||||
|
@ -52,6 +53,19 @@
|
|||
self.layer.contentsScale = _defaultImage.scale;
|
||||
self.layer.contents = (__bridge id)_defaultImage.CGImage;
|
||||
}
|
||||
if ([imageURL.pathExtension caseInsensitiveCompare:@"gif"] == NSOrderedSame) {
|
||||
_downloadToken = [_imageDownloader downloadDataForURL:imageURL block:^(NSData *data, NSError *error) {
|
||||
if (data) {
|
||||
CAKeyframeAnimation *animation = [RCTConvert GIF:data];
|
||||
CGImageRef firstFrame = (__bridge CGImageRef)animation.values.firstObject;
|
||||
self.layer.bounds = CGRectMake(0, 0, CGImageGetWidth(firstFrame), CGImageGetHeight(firstFrame));
|
||||
self.layer.contentsScale = 1.0;
|
||||
self.layer.contentsGravity = kCAGravityResizeAspect;
|
||||
[self.layer addAnimation:animation forKey:@"contents"];
|
||||
}
|
||||
// TODO: handle errors
|
||||
}];
|
||||
} else {
|
||||
_downloadToken = [_imageDownloader downloadImageForURL:imageURL size:self.bounds.size scale:RCTScreenScale() block:^(UIImage *image, NSError *error) {
|
||||
if (image) {
|
||||
self.layer.contentsScale = image.scale;
|
||||
|
@ -60,6 +74,7 @@
|
|||
// TODO: handle errors
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setImageURL:(NSURL *)imageURL
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
@implementation RCTNetworkImageViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
RCTNetworkImageView *view = [[RCTNetworkImageView alloc] initWithFrame:CGRectZero imageDownloader:[RCTImageDownloader sharedInstance]];
|
||||
view.contentMode = UIViewContentModeScaleAspectFill;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
@implementation RCTRawTextManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[UIView alloc] init];
|
||||
}
|
||||
|
|
|
@ -32,6 +32,6 @@
|
|||
@property (nonatomic, assign) BOOL centerContent;
|
||||
@property (nonatomic, copy) NSArray *stickyHeaderIndices;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUIManager.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "UIView+ReactKit.h"
|
||||
|
||||
CGFloat const ZINDEX_DEFAULT = 0;
|
||||
|
@ -122,6 +123,7 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
|||
*/
|
||||
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
|
||||
{
|
||||
//TODO: shouldn't this call super if _shouldDisableScrollInteraction returns NO?
|
||||
return ![self _shouldDisableScrollInteraction];
|
||||
}
|
||||
|
||||
|
@ -260,9 +262,14 @@ CGFloat const ZINDEX_STICKY_HEADER = 50;
|
|||
|
||||
@synthesize nativeMainScrollDelegate = _nativeMainScrollDelegate;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if ((self = [super initWithFrame:CGRectZero])) {
|
||||
|
||||
_eventDispatcher = eventDispatcher;
|
||||
_scrollView = [[RCTCustomScrollView alloc] initWithFrame:CGRectZero];
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
@implementation RCTScrollViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTScrollView alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
return [[RCTScrollView alloc] initWithEventDispatcher:self.eventDispatcher];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(alwaysBounceHorizontal)
|
||||
|
@ -36,7 +36,7 @@ RCT_EXPORT_VIEW_PROPERTY(contentInset);
|
|||
RCT_EXPORT_VIEW_PROPERTY(scrollIndicatorInsets);
|
||||
RCT_EXPORT_VIEW_PROPERTY(contentOffset);
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
+ (NSDictionary *)constantsToExport
|
||||
{
|
||||
return
|
||||
@{
|
||||
|
|
|
@ -9,14 +9,26 @@
|
|||
|
||||
@implementation RCTStaticImageManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTStaticImage alloc] init];
|
||||
}
|
||||
|
||||
RCT_REMAP_VIEW_PROPERTY(src, image)
|
||||
RCT_REMAP_VIEW_PROPERTY(resizeMode, contentMode)
|
||||
|
||||
- (void)set_src:(id)json forView:(RCTStaticImage *)view withDefaultView:(RCTStaticImage *)defaultView
|
||||
{
|
||||
if (json) {
|
||||
if ([json isKindOfClass:[NSString class]] && [[json pathExtension] caseInsensitiveCompare:@"gif"] == NSOrderedSame) {
|
||||
[view.layer addAnimation:[RCTConvert GIF:json] forKey:@"contents"];
|
||||
} else {
|
||||
view.image = [RCTConvert UIImage:json];
|
||||
}
|
||||
} else {
|
||||
view.image = defaultView.image;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)set_capInsets:(id)json forView:(RCTStaticImage *)view withDefaultView:(RCTStaticImage *)defaultView
|
||||
{
|
||||
view.capInsets = json ? [RCTConvert UIEdgeInsets:json] : defaultView.capInsets;
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
@property (nonatomic, assign) BOOL autoCorrect;
|
||||
@property (nonatomic, assign) UIEdgeInsets paddingEdgeInsets; // TODO: contentInset
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher;
|
||||
|
||||
@end
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
BOOL _jsRequestingFirstResponder;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
RCT_NOT_DESIGNATED_INITIALIZER();
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame eventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
if ((self = [super initWithFrame:CGRectZero])) {
|
||||
|
||||
_eventDispatcher = eventDispatcher;
|
||||
[self addTarget:self action:@selector(_textFieldDidChange) forControlEvents:UIControlEventEditingChanged];
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
@implementation RCTTextFieldManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTTextField alloc] initWithFrame:CGRectZero eventDispatcher:eventDispatcher];
|
||||
return [[RCTTextField alloc] initWithEventDispatcher:self.eventDispatcher];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(caretHidden)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
@implementation RCTTextManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
UILabel *label = [[UILabel alloc] init];
|
||||
label.numberOfLines = 0;
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
@implementation RCTUIActivityIndicatorViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
|
||||
return [[UIActivityIndicatorView alloc] init];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(activityIndicatorViewStyle)
|
||||
|
@ -28,7 +28,7 @@ RCT_EXPORT_VIEW_PROPERTY(color)
|
|||
}
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
+ (NSDictionary *)constantsToExport
|
||||
{
|
||||
return
|
||||
@{
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
#import "RCTExport.h"
|
||||
|
||||
@class RCTEventDispatcher;
|
||||
|
||||
@interface RCTUIViewManager : NSObject <RCTNativeViewModule>
|
||||
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, readonly) RCTEventDispatcher *eventDispatcher;
|
||||
|
||||
@end
|
||||
|
|
|
@ -3,13 +3,38 @@
|
|||
#import "RCTUIViewManager.h"
|
||||
|
||||
#import "RCTConvert.h"
|
||||
#import "RCTEventDispatcher.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTShadowView.h"
|
||||
#import "RCTView.h"
|
||||
|
||||
@implementation RCTUIViewManager
|
||||
{
|
||||
__weak RCTEventDispatcher *_eventDispatcher;
|
||||
}
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventDispatcher = eventDispatcher;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (NSString *)moduleName
|
||||
{
|
||||
// Default implementation, works in most cases
|
||||
NSString *name = NSStringFromClass(self);
|
||||
if ([name hasPrefix:@"RCTUI"]) {
|
||||
name = [name substringFromIndex:@"RCT".length];
|
||||
}
|
||||
if ([name hasSuffix:@"Manager"]) {
|
||||
name = [name substringToIndex:name.length - @"Manager".length];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[UIView alloc] init];
|
||||
}
|
||||
|
@ -29,7 +54,7 @@ RCT_REMAP_VIEW_PROPERTY(shadowRadius, layer.shadowRadius)
|
|||
RCT_REMAP_VIEW_PROPERTY(borderColor, layer.borderColor);
|
||||
RCT_REMAP_VIEW_PROPERTY(borderRadius, layer.cornerRadius)
|
||||
RCT_REMAP_VIEW_PROPERTY(borderWidth, layer.borderWidth)
|
||||
RCT_REMAP_VIEW_PROPERTY(transformMatrix, view.layer.transform)
|
||||
RCT_REMAP_VIEW_PROPERTY(transformMatrix, layer.transform)
|
||||
|
||||
- (void)set_overflow:(id)json
|
||||
forView:(UIView *)view
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
@implementation RCTViewManager
|
||||
|
||||
- (UIView *)viewWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher
|
||||
- (UIView *)view
|
||||
{
|
||||
return [[RCTView alloc] init];
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel)
|
||||
RCT_EXPORT_VIEW_PROPERTY(pointerEvents)
|
||||
|
||||
@end
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
|
||||
- (void)rightButtonTapped
|
||||
{
|
||||
[_eventDispatcher sendRawEventWithType:@"topNavRightButtonTap" body:@{@"target":_navItem.reactTag}];
|
||||
[_eventDispatcher sendEventWithName:@"topNavRightButtonTap" body:@{@"target":_navItem.reactTag}];
|
||||
}
|
||||
|
||||
- (void)didMoveToParentViewController:(UIViewController *)parent
|
||||
|
|
Loading…
Reference in New Issue