mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-05-19 04:52:51 +08:00
Implemented thread control for exported methods
This commit is contained in:
@@ -34,92 +34,88 @@ RCT_EXPORT_METHOD(showActionSheetWithOptions:(NSDictionary *)options
|
||||
failureCallback:(RCTResponseSenderBlock)failureCallback
|
||||
successCallback:(RCTResponseSenderBlock)successCallback)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
UIActionSheet *actionSheet = [[UIActionSheet alloc] init];
|
||||
UIActionSheet *actionSheet = [[UIActionSheet alloc] init];
|
||||
|
||||
actionSheet.title = options[@"title"];
|
||||
actionSheet.title = options[@"title"];
|
||||
|
||||
for (NSString *option in options[@"options"]) {
|
||||
[actionSheet addButtonWithTitle:option];
|
||||
}
|
||||
for (NSString *option in options[@"options"]) {
|
||||
[actionSheet addButtonWithTitle:option];
|
||||
}
|
||||
|
||||
if (options[@"destructiveButtonIndex"]) {
|
||||
actionSheet.destructiveButtonIndex = [options[@"destructiveButtonIndex"] integerValue];
|
||||
}
|
||||
if (options[@"cancelButtonIndex"]) {
|
||||
actionSheet.cancelButtonIndex = [options[@"cancelButtonIndex"] integerValue];
|
||||
}
|
||||
if (options[@"destructiveButtonIndex"]) {
|
||||
actionSheet.destructiveButtonIndex = [options[@"destructiveButtonIndex"] integerValue];
|
||||
}
|
||||
if (options[@"cancelButtonIndex"]) {
|
||||
actionSheet.cancelButtonIndex = [options[@"cancelButtonIndex"] integerValue];
|
||||
}
|
||||
|
||||
actionSheet.delegate = self;
|
||||
actionSheet.delegate = self;
|
||||
|
||||
_callbacks[keyForInstance(actionSheet)] = successCallback;
|
||||
_callbacks[RCTKeyForInstance(actionSheet)] = successCallback;
|
||||
|
||||
UIWindow *appWindow = [[[UIApplication sharedApplication] delegate] window];
|
||||
if (appWindow == nil) {
|
||||
RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", options);
|
||||
return;
|
||||
}
|
||||
[actionSheet showInView:appWindow];
|
||||
});
|
||||
UIWindow *appWindow = [[[UIApplication sharedApplication] delegate] window];
|
||||
if (appWindow == nil) {
|
||||
RCTLogError(@"Tried to display action sheet but there is no application window. options: %@", options);
|
||||
return;
|
||||
}
|
||||
[actionSheet showInView:appWindow];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
|
||||
failureCallback:(RCTResponseSenderBlock)failureCallback
|
||||
successCallback:(RCTResponseSenderBlock)successCallback)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSMutableArray *items = [NSMutableArray array];
|
||||
id message = options[@"message"];
|
||||
id url = options[@"url"];
|
||||
if ([message isKindOfClass:[NSString class]]) {
|
||||
[items addObject:message];
|
||||
}
|
||||
if ([url isKindOfClass:[NSString class]]) {
|
||||
[items addObject:[NSURL URLWithString:url]];
|
||||
}
|
||||
if ([items count] == 0) {
|
||||
failureCallback(@[@"No `url` or `message` to share"]);
|
||||
return;
|
||||
}
|
||||
UIActivityViewController *share = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
|
||||
UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
|
||||
if ([share respondsToSelector:@selector(setCompletionWithItemsHandler:)]) {
|
||||
share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
||||
if (activityError) {
|
||||
failureCallback(@[[activityError localizedDescription]]);
|
||||
} else {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
NSMutableArray *items = [NSMutableArray array];
|
||||
id message = options[@"message"];
|
||||
id url = options[@"url"];
|
||||
if ([message isKindOfClass:[NSString class]]) {
|
||||
[items addObject:message];
|
||||
}
|
||||
if ([url isKindOfClass:[NSString class]]) {
|
||||
[items addObject:[NSURL URLWithString:url]];
|
||||
}
|
||||
if ([items count] == 0) {
|
||||
failureCallback(@[@"No `url` or `message` to share"]);
|
||||
return;
|
||||
}
|
||||
UIActivityViewController *share = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil];
|
||||
UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
|
||||
if ([share respondsToSelector:@selector(setCompletionWithItemsHandler:)]) {
|
||||
share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
||||
if (activityError) {
|
||||
failureCallback(@[[activityError localizedDescription]]);
|
||||
} else {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
||||
|
||||
if (![UIActivityViewController instancesRespondToSelector:@selector(completionWithItemsHandler)]) {
|
||||
// Legacy iOS 7 implementation
|
||||
share.completionHandler = ^(NSString *activityType, BOOL completed) {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
};
|
||||
} else
|
||||
if (![UIActivityViewController instancesRespondToSelector:@selector(completionWithItemsHandler)]) {
|
||||
// Legacy iOS 7 implementation
|
||||
share.completionHandler = ^(NSString *activityType, BOOL completed) {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
};
|
||||
} else
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
// iOS 8 version
|
||||
share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
};
|
||||
}
|
||||
{
|
||||
// iOS 8 version
|
||||
share.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
|
||||
successCallback(@[@(completed), (activityType ?: [NSNull null])]);
|
||||
};
|
||||
}
|
||||
[ctrl presentViewController:share animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
[ctrl presentViewController:share animated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark UIActionSheetDelegate Methods
|
||||
|
||||
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
NSString *key = keyForInstance(actionSheet);
|
||||
NSString *key = RCTKeyForInstance(actionSheet);
|
||||
RCTResponseSenderBlock callback = _callbacks[key];
|
||||
if (callback) {
|
||||
callback(@[@(buttonIndex)]);
|
||||
@@ -133,7 +129,7 @@ RCT_EXPORT_METHOD(showShareActionSheetWithOptions:(NSDictionary *)options
|
||||
|
||||
#pragma mark Private
|
||||
|
||||
NS_INLINE NSString *keyForInstance(id instance)
|
||||
static NSString *RCTKeyForInstance(id instance)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%p", instance];
|
||||
}
|
||||
|
||||
@@ -68,6 +68,11 @@ RCT_EXPORT_MODULE()
|
||||
return self;
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return _bridge.uiManager.methodQueue;
|
||||
}
|
||||
|
||||
- (id (^)(CGFloat))interpolateFrom:(CGFloat[])fromArray to:(CGFloat[])toArray count:(NSUInteger)count typeName:(const char *)typeName
|
||||
{
|
||||
if (count == 1) {
|
||||
|
||||
@@ -33,7 +33,9 @@ typedef struct {
|
||||
CLLocationAccuracy accuracy;
|
||||
} RCTLocationOptions;
|
||||
|
||||
static RCTLocationOptions RCTLocationOptionsWithJSON(id json)
|
||||
@implementation RCTConvert (RCTLocationOptions)
|
||||
|
||||
+ (RCTLocationOptions)RCTLocationOptions:(id)json
|
||||
{
|
||||
NSDictionary *options = [RCTConvert NSDictionary:json];
|
||||
return (RCTLocationOptions){
|
||||
@@ -43,6 +45,8 @@ static RCTLocationOptions RCTLocationOptionsWithJSON(id json)
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSDictionary *RCTPositionError(RCTPositionErrorCode code, NSString *msg /* nil for default */)
|
||||
{
|
||||
if (!msg) {
|
||||
@@ -121,6 +125,7 @@ RCT_EXPORT_MODULE()
|
||||
- (void)dealloc
|
||||
{
|
||||
[_locationManager stopUpdatingLocation];
|
||||
_locationManager.delegate = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private API
|
||||
@@ -153,41 +158,33 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
#pragma mark - Public API
|
||||
|
||||
RCT_EXPORT_METHOD(startObserving:(NSDictionary *)optionsJSON)
|
||||
RCT_EXPORT_METHOD(startObserving:(RCTLocationOptions)options)
|
||||
{
|
||||
[self checkLocationConfig];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Select best options
|
||||
_observerOptions = options;
|
||||
for (RCTLocationRequest *request in _pendingRequests) {
|
||||
_observerOptions.accuracy = MIN(_observerOptions.accuracy, request.options.accuracy);
|
||||
}
|
||||
|
||||
// Select best options
|
||||
_observerOptions = RCTLocationOptionsWithJSON(optionsJSON);
|
||||
for (RCTLocationRequest *request in _pendingRequests) {
|
||||
_observerOptions.accuracy = MIN(_observerOptions.accuracy, request.options.accuracy);
|
||||
}
|
||||
|
||||
_locationManager.desiredAccuracy = _observerOptions.accuracy;
|
||||
[self beginLocationUpdates];
|
||||
_observingLocation = YES;
|
||||
|
||||
});
|
||||
_locationManager.desiredAccuracy = _observerOptions.accuracy;
|
||||
[self beginLocationUpdates];
|
||||
_observingLocation = YES;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(stopObserving)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Stop observing
|
||||
_observingLocation = NO;
|
||||
|
||||
// Stop observing
|
||||
_observingLocation = NO;
|
||||
|
||||
// Stop updating if no pending requests
|
||||
if (_pendingRequests.count == 0) {
|
||||
[_locationManager stopUpdatingLocation];
|
||||
}
|
||||
|
||||
});
|
||||
// Stop updating if no pending requests
|
||||
if (_pendingRequests.count == 0) {
|
||||
[_locationManager stopUpdatingLocation];
|
||||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(getCurrentPosition:(NSDictionary *)optionsJSON
|
||||
RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
|
||||
withSuccessCallback:(RCTResponseSenderBlock)successBlock
|
||||
errorCallback:(RCTResponseSenderBlock)errorBlock)
|
||||
{
|
||||
@@ -198,56 +195,49 @@ RCT_EXPORT_METHOD(getCurrentPosition:(NSDictionary *)optionsJSON
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
if (![CLLocationManager locationServicesEnabled]) {
|
||||
if (errorBlock) {
|
||||
errorBlock(@[
|
||||
RCTPositionError(RCTPositionErrorUnavailable, @"Location services disabled.")
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
|
||||
if (errorBlock) {
|
||||
errorBlock(@[
|
||||
RCTPositionError(RCTPositionErrorDenied, nil)
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get options
|
||||
RCTLocationOptions options = RCTLocationOptionsWithJSON(optionsJSON);
|
||||
|
||||
// Check if previous recorded location exists and is good enough
|
||||
if (_lastLocationEvent &&
|
||||
CFAbsoluteTimeGetCurrent() - [RCTConvert NSTimeInterval:_lastLocationEvent[@"timestamp"]] < options.maximumAge &&
|
||||
[_lastLocationEvent[@"coords"][@"accuracy"] doubleValue] >= options.accuracy) {
|
||||
|
||||
// Call success block with most recent known location
|
||||
successBlock(@[_lastLocationEvent]);
|
||||
if (![CLLocationManager locationServicesEnabled]) {
|
||||
if (errorBlock) {
|
||||
errorBlock(@[
|
||||
RCTPositionError(RCTPositionErrorUnavailable, @"Location services disabled.")
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create request
|
||||
RCTLocationRequest *request = [[RCTLocationRequest alloc] init];
|
||||
request.successBlock = successBlock;
|
||||
request.errorBlock = errorBlock ?: ^(NSArray *args){};
|
||||
request.options = options;
|
||||
request.timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:options.timeout
|
||||
target:self
|
||||
selector:@selector(timeout:)
|
||||
userInfo:request
|
||||
repeats:NO];
|
||||
[_pendingRequests addObject:request];
|
||||
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
|
||||
if (errorBlock) {
|
||||
errorBlock(@[
|
||||
RCTPositionError(RCTPositionErrorDenied, nil)
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Configure location manager and begin updating location
|
||||
_locationManager.desiredAccuracy = MIN(_locationManager.desiredAccuracy, options.accuracy);
|
||||
[self beginLocationUpdates];
|
||||
// Check if previous recorded location exists and is good enough
|
||||
if (_lastLocationEvent &&
|
||||
CFAbsoluteTimeGetCurrent() - [RCTConvert NSTimeInterval:_lastLocationEvent[@"timestamp"]] < options.maximumAge &&
|
||||
[_lastLocationEvent[@"coords"][@"accuracy"] doubleValue] >= options.accuracy) {
|
||||
|
||||
});
|
||||
// Call success block with most recent known location
|
||||
successBlock(@[_lastLocationEvent]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create request
|
||||
RCTLocationRequest *request = [[RCTLocationRequest alloc] init];
|
||||
request.successBlock = successBlock;
|
||||
request.errorBlock = errorBlock ?: ^(NSArray *args){};
|
||||
request.options = options;
|
||||
request.timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:options.timeout
|
||||
target:self
|
||||
selector:@selector(timeout:)
|
||||
userInfo:request
|
||||
repeats:NO];
|
||||
[_pendingRequests addObject:request];
|
||||
|
||||
// Configure location manager and begin updating location
|
||||
_locationManager.desiredAccuracy = MIN(_locationManager.desiredAccuracy, options.accuracy);
|
||||
[self beginLocationUpdates];
|
||||
}
|
||||
|
||||
#pragma mark - CLLocationManagerDelegate
|
||||
|
||||
@@ -62,8 +62,10 @@ RCT_EXPORT_METHOD(openURL:(NSURL *)URL)
|
||||
RCT_EXPORT_METHOD(canOpenURL:(NSURL *)URL
|
||||
callback:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:URL];
|
||||
callback(@[@(canOpen)]);
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:URL];
|
||||
callback(@[@(canOpen)]);
|
||||
});
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
|
||||
@@ -15,14 +15,24 @@
|
||||
|
||||
@interface RCTTestModule : NSObject <RCTBridgeModule>
|
||||
|
||||
// This is typically polled while running the runloop until true
|
||||
@property (nonatomic, readonly, getter=isDone) BOOL done;
|
||||
|
||||
// This is used to give meaningful names to snapshot image files.
|
||||
@property (nonatomic, assign) SEL testSelector;
|
||||
/**
|
||||
* The snapshot test controller for this module.
|
||||
*/
|
||||
@property (nonatomic, weak) FBSnapshotTestController *controller;
|
||||
|
||||
/**
|
||||
* This is the view to be snapshotted.
|
||||
*/
|
||||
@property (nonatomic, weak) UIView *view;
|
||||
|
||||
- (instancetype)initWithSnapshotController:(FBSnapshotTestController *)controller view:(UIView *)view;
|
||||
/**
|
||||
* This is used to give meaningful names to snapshot image files.
|
||||
*/
|
||||
@property (nonatomic, assign) SEL testSelector;
|
||||
|
||||
/**
|
||||
* This is typically polled while running the runloop until true.
|
||||
*/
|
||||
@property (nonatomic, readonly, getter=isDone) BOOL done;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,21 +12,25 @@
|
||||
#import "FBSnapshotTestController.h"
|
||||
#import "RCTAssert.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
@implementation RCTTestModule
|
||||
{
|
||||
__weak FBSnapshotTestController *_snapshotController;
|
||||
__weak UIView *_view;
|
||||
NSMutableDictionary *_snapshotCounter;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
||||
- (instancetype)initWithSnapshotController:(FBSnapshotTestController *)controller view:(UIView *)view
|
||||
- (dispatch_queue_t)methodQueue
|
||||
{
|
||||
return _bridge.uiManager.methodQueue;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_snapshotController = controller;
|
||||
_view = view;
|
||||
_snapshotCounter = [NSMutableDictionary new];
|
||||
}
|
||||
return self;
|
||||
@@ -34,30 +38,29 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
RCT_EXPORT_METHOD(verifySnapshot:(RCTResponseSenderBlock)callback)
|
||||
{
|
||||
if (!_snapshotController) {
|
||||
RCTLogWarn(@"No snapshot controller configured.");
|
||||
callback(@[]);
|
||||
return;
|
||||
}
|
||||
RCTAssert(_controller != nil, @"No snapshot controller configured.");
|
||||
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString *testName = NSStringFromSelector(_testSelector);
|
||||
_snapshotCounter[testName] = @([_snapshotCounter[testName] integerValue] + 1);
|
||||
_snapshotCounter[testName] = [@([_snapshotCounter[testName] integerValue] + 1) stringValue];
|
||||
|
||||
NSError *error = nil;
|
||||
BOOL success = [_snapshotController compareSnapshotOfView:_view
|
||||
selector:_testSelector
|
||||
identifier:[_snapshotCounter[testName] stringValue]
|
||||
error:&error];
|
||||
BOOL success = [_controller compareSnapshotOfView:_view
|
||||
selector:_testSelector
|
||||
identifier:_snapshotCounter[testName]
|
||||
error:&error];
|
||||
|
||||
RCTAssert(success, @"Snapshot comparison failed: %@", error);
|
||||
callback(@[]);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(markTestCompleted)
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, RCTSparseArray *viewRegistry) {
|
||||
_done = YES;
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
@implementation RCTTestRunner
|
||||
{
|
||||
FBSnapshotTestController *_snapshotController;
|
||||
FBSnapshotTestController *_testController;
|
||||
}
|
||||
|
||||
- (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir
|
||||
@@ -27,8 +27,8 @@
|
||||
if ((self = [super init])) {
|
||||
NSString *sanitizedAppName = [app stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
|
||||
sanitizedAppName = [sanitizedAppName stringByReplacingOccurrencesOfString:@"\\" withString:@"-"];
|
||||
_snapshotController = [[FBSnapshotTestController alloc] initWithTestName:sanitizedAppName];
|
||||
_snapshotController.referenceImagesDirectory = referenceDir;
|
||||
_testController = [[FBSnapshotTestController alloc] initWithTestName:sanitizedAppName];
|
||||
_testController.referenceImagesDirectory = referenceDir;
|
||||
_scriptURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.includeRequire.runModule.bundle?dev=true", app]];
|
||||
}
|
||||
return self;
|
||||
@@ -36,12 +36,12 @@
|
||||
|
||||
- (void)setRecordMode:(BOOL)recordMode
|
||||
{
|
||||
_snapshotController.recordMode = recordMode;
|
||||
_testController.recordMode = recordMode;
|
||||
}
|
||||
|
||||
- (BOOL)recordMode
|
||||
{
|
||||
return _snapshotController.recordMode;
|
||||
return _testController.recordMode;
|
||||
}
|
||||
|
||||
- (void)runTest:(SEL)test module:(NSString *)moduleName
|
||||
@@ -59,27 +59,22 @@
|
||||
|
||||
- (void)runTest:(SEL)test module:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock
|
||||
{
|
||||
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
|
||||
if ([vc.view isKindOfClass:[RCTRootView class]]) {
|
||||
[(RCTRootView *)vc.view invalidate]; // Make sure the normal app view doesn't interfere
|
||||
}
|
||||
vc.view = [[UIView alloc] init];
|
||||
|
||||
RCTTestModule *testModule = [[RCTTestModule alloc] initWithSnapshotController:_snapshotController view:nil];
|
||||
testModule.testSelector = test;
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_scriptURL
|
||||
moduleProvider:^(){
|
||||
return @[testModule];
|
||||
}
|
||||
launchOptions:nil];
|
||||
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
|
||||
moduleName:moduleName];
|
||||
testModule.view = rootView;
|
||||
[vc.view addSubview:rootView]; // Add as subview so it doesn't get resized
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:_scriptURL
|
||||
moduleName:moduleName
|
||||
launchOptions:nil];
|
||||
rootView.initialProperties = initialProps;
|
||||
rootView.frame = CGRectMake(0, 0, 320, 2000); // Constant size for testing on multiple devices
|
||||
|
||||
NSString *testModuleName = RCTBridgeModuleNameForClass([RCTTestModule class]);
|
||||
RCTTestModule *testModule = rootView.bridge.modules[testModuleName];
|
||||
testModule.controller = _testController;
|
||||
testModule.testSelector = test;
|
||||
testModule.view = rootView;
|
||||
|
||||
UIViewController *vc = [UIApplication sharedApplication].delegate.window.rootViewController;
|
||||
vc.view = [[UIView alloc] init];
|
||||
[vc.view addSubview:rootView]; // Add as subview so it doesn't get resized
|
||||
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
NSString *error = [[RCTRedBox sharedInstance] currentErrorMessage];
|
||||
while ([date timeIntervalSinceNow] > 0 && ![testModule isDone] && error == nil) {
|
||||
|
||||
Reference in New Issue
Block a user