Changed methodQueue to a property

This commit is contained in:
Nick Lockwood 2015-06-19 04:18:54 -07:00
parent cf0e40ad3d
commit c8c254ce13
6 changed files with 84 additions and 83 deletions

View File

@ -79,25 +79,19 @@ RCT_EXPORT_MODULE()
{
RCTBridge *_bridge;
BOOL _testMethodCalled;
dispatch_queue_t _queue;
}
@end
@implementation RCTBridgeTests
RCT_EXPORT_MODULE(TestModule)
@synthesize methodQueue = _methodQueue;
- (dispatch_queue_t)methodQueue
{
return _queue;
}
RCT_EXPORT_MODULE(TestModule)
- (void)setUp
{
[super setUp];
_queue = dispatch_queue_create("com.facebook.React.TestQueue", DISPATCH_QUEUE_SERIAL);
_bridge = [[RCTBridge alloc] initWithBundleURL:nil
moduleProvider:^{ return @[self]; }
launchOptions:nil];
@ -151,7 +145,7 @@ RCT_EXPORT_MODULE(TestModule)
[_bridge.batchedBridge _handleBuffer:buffer context:RCTGetExecutorID(executor)];
dispatch_sync(_queue, ^{
dispatch_sync(_methodQueue, ^{
// clear the queue
XCTAssertTrue(_testMethodCalled);
});

View File

@ -37,11 +37,6 @@ RCT_EXPORT_MODULE()
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (dispatch_queue_t)methodQueue
{
return dispatch_queue_create("com.facebook.React.LinkingManager", DISPATCH_QUEUE_SERIAL);
}
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)URL
sourceApplication:(NSString *)sourceApplication

View File

@ -211,10 +211,10 @@ typedef void (^RCTDataLoaderCallback)(NSData *data, NSString *MIMEType, NSError
{
NSInteger _currentRequestID;
NSMapTable *_activeRequests;
dispatch_queue_t _methodQueue;
}
@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;
RCT_EXPORT_MODULE()
@ -222,7 +222,6 @@ RCT_EXPORT_MODULE()
{
if ((self = [super init])) {
_currentRequestID = 0;
_methodQueue = dispatch_queue_create("com.facebook.React.RCTDataManager", DISPATCH_QUEUE_SERIAL);
_activeRequests = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory
valueOptions:NSPointerFunctionsStrongMemory
capacity:0];
@ -230,11 +229,6 @@ RCT_EXPORT_MODULE()
return self;
}
- (dispatch_queue_t)methodQueue
{
return _methodQueue;
}
- (void)buildRequest:(NSDictionary *)query
responseSender:(RCTResponseSenderBlock)responseSender
{

View File

@ -31,8 +31,6 @@ NSString *const RCTReloadNotification = @"RCTReloadNotification";
NSString *const RCTJavaScriptDidLoadNotification = @"RCTJavaScriptDidLoadNotification";
NSString *const RCTJavaScriptDidFailToLoadNotification = @"RCTJavaScriptDidFailToLoadNotification";
dispatch_queue_t const RCTJSThread = nil;
/**
* Must be kept in sync with `MessageQueue.js`.
*/
@ -163,7 +161,6 @@ static NSDictionary *RCTJSErrorFromNSError(NSError *error)
SEL _selector;
NSMethodSignature *_methodSignature;
NSArray *_argumentBlocks;
dispatch_block_t _methodQueue;
}
- (instancetype)initWithObjCMethodName:(NSString *)objCMethodName
@ -567,14 +564,19 @@ static NSDictionary *RCTRemoteModulesConfig(NSDictionary *modulesByName)
@implementation RCTBridge
static id<RCTJavaScriptExecutor> _latestJSExecutor;
#if RCT_DEBUG
dispatch_queue_t RCTJSThread;
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Set up JS thread
RCTJSThread = (id)kCFNull;
#if RCT_DEBUG
// Set up module classes
static unsigned int classCount;
Class *classes = objc_copyClassList(&classCount);
@ -587,7 +589,8 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
if (class_conformsToProtocol(superclass, @protocol(RCTBridgeModule)))
{
if (![RCTModuleClassesByID containsObject:cls]) {
RCTLogError(@"Class %@ was not exported. Did you forget to use RCT_EXPORT_MODULE()?", NSStringFromClass(cls));
RCTLogError(@"Class %@ was not exported. Did you forget to use "
"RCT_EXPORT_MODULE()?", NSStringFromClass(cls));
}
break;
}
@ -597,11 +600,11 @@ static id<RCTJavaScriptExecutor> _latestJSExecutor;
free(classes);
#endif
});
}
#endif
- (instancetype)initWithBundleURL:(NSURL *)bundleURL
moduleProvider:(RCTBridgeModuleProviderBlock)block
launchOptions:(NSDictionary *)launchOptions
@ -741,7 +744,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
__weak id<RCTJavaScriptExecutor> _javaScriptExecutor;
RCTSparseArray *_modulesByID;
RCTSparseArray *_queuesByID;
dispatch_queue_t _methodQueue;
NSDictionary *_modulesByName;
CADisplayLink *_mainDisplayLink;
CADisplayLink *_jsDisplayLink;
@ -783,7 +785,6 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
* Initialize and register bridge modules *before* adding the display link
* so we don't have threading issues
*/
_methodQueue = dispatch_queue_create("com.facebook.React.BridgeMethodQueue", DISPATCH_QUEUE_SERIAL);
[self registerModules];
/**
@ -896,21 +897,49 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
}
}
// Get method queues
[_modulesByID enumerateObjectsUsingBlock:
^(id<RCTBridgeModule> module, NSNumber *moduleID, __unused BOOL *stop) {
if ([module respondsToSelector:@selector(methodQueue)]) {
dispatch_queue_t queue = [module methodQueue];
if (queue) {
_queuesByID[moduleID] = queue;
} else {
_queuesByID[moduleID] = (id)kCFNull;
// Set/get method queues
[_modulesByID enumerateObjectsUsingBlock:^(id<RCTBridgeModule> module, NSNumber *moduleID, __unused BOOL *stop) {
dispatch_queue_t queue = nil;
BOOL implementsMethodQueue = [module respondsToSelector:@selector(methodQueue)];
if (implementsMethodQueue) {
queue = [module methodQueue];
}
if (!queue) {
// Need to cache queueNames because they aren't retained by dispatch_queue
static NSMutableDictionary *queueNames;
if (!queueNames) {
queueNames = [[NSMutableDictionary alloc] init];
}
NSString *moduleName = RCTBridgeModuleNameForClass([module class]);
NSString *queueName = queueNames[moduleName];
if (!queueName) {
queueName = [NSString stringWithFormat:@"com.facebook.React.%@Queue", moduleName];
queueNames[moduleName] = queueName;
}
// Create new queue
queue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
// assign it to the module
if (implementsMethodQueue) {
@try {
[(id)module setValue:queue forKey:@"methodQueue"];
}
@catch (NSException *exception) {
RCTLogError(@"%@ is returning nil for it's methodQueue, which is not "
"permitted. You must either return a pre-initialized "
"queue, or @synthesize the methodQueue to let the bridge "
"create a queue for you.", moduleName);
}
}
}
_queuesByID[moduleID] = queue;
if ([module conformsToProtocol:@protocol(RCTFrameUpdateObserver)]) {
[_frameUpdateObservers addObject:module];
}
}
}];
}
@ -1166,10 +1195,10 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
queue = _queuesByID[moduleID];
}
if (queue == (id)kCFNull) {
if (queue == RCTJSThread) {
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
} else {
dispatch_async(queue ?: _methodQueue, block);
} else if (queue) {
dispatch_async(queue, block);
}
}
@ -1309,9 +1338,9 @@ RCT_INNER_BRIDGE_ONLY(_invokeAndProcessModule:(__unused NSString *)module
RCTProfileEndEvent(RCTCurrentThreadName(), @"objc_call,dispatch_async", @{ @"calls": @(calls.count) });
};
if (queue == (id)kCFNull) {
if (queue == RCTJSThread) {
[_javaScriptExecutor executeBlockOnJavaScriptQueue:block];
} else {
} else if (queue) {
dispatch_async(queue, block);
}
}

View File

@ -41,7 +41,7 @@ typedef void (^RCTPromiseRejectBlock)(NSError *error);
*
* NOTE: RCTJSThread is not a real libdispatch queue
*/
extern const dispatch_queue_t RCTJSThread;
extern dispatch_queue_t RCTJSThread;
/**
* Provides the interface needed to register a bridge module.
@ -53,10 +53,33 @@ extern const dispatch_queue_t RCTJSThread;
* A reference to the RCTBridge. Useful for modules that require access
* to bridge features, such as sending events or making JS calls. This
* will be set automatically by the bridge when it initializes the module.
* To implement this in your module, just add @synthesize bridge = _bridge;
* To implement this in your module, just add `@synthesize bridge = _bridge;`
*/
@property (nonatomic, weak) RCTBridge *bridge;
/**
* The queue that will be used to call all exported methods. If omitted, this
* will call on a default background queue, which is avoids blocking the main
* thread.
*
* If the methods in your module need to interact with UIKit methods, they will
* probably need to call those on the main thread, as most of UIKit is main-
* thread-only. You can tell React Native to call your module methods on the
* main thread by returning a reference to the main queue, like this:
*
* - (dispatch_queue_t)methodQueue
* {
* return dispatch_get_main_queue();
* }
*
* If you don't want to specify the queue yourself, but you need to use it
* inside your class (e.g. if you have internal methods that need to disaptch
* onto that queue), you can just add `@synthesize methodQueue = _methodQueue;`
* and the bridge will populate the methodQueue property for you automatically
* when it initializes the module.
*/
@property (nonatomic, weak, readonly) dispatch_queue_t methodQueue;
/**
* Place this macro in your class implementation to automatically register
* your module with the bridge when it loads. The optional js_name argument
@ -180,38 +203,6 @@ extern const dispatch_queue_t RCTJSThread;
return @[@#js_name, @#method]; \
} \
/**
* The queue that will be used to call all exported methods. If omitted, this
* will call on the default background queue, which is avoids blocking the main
* thread.
*
* If the methods in your module need to interact with UIKit methods, they will
* probably need to call those on the main thread, as most of UIKit is main-
* thread-only. You can tell React Native to call your module methods on the
* main thread by returning a reference to the main queue, like this:
*
* - (dispatch_queue_t)methodQueue
* {
* return dispatch_get_main_queue();
* }
*
* If your methods perform heavy work such as synchronous filesystem or network
* access, you probably don't want to block the default background queue, as
* this will stall other methods. Instead, you should return a custom serial
* queue, like this:
*
* - (dispatch_queue_t)methodQueue
* {
* return dispatch_queue_create("com.mydomain.FileQueue", DISPATCH_QUEUE_SERIAL);
* }
*
* Alternatively, if only some methods of the module should be executed on a
* particular queue you can leave this method unimplemented, and simply
* dispatch_async() to the required queue within the method itself.
*/
- (dispatch_queue_t)methodQueue;
/**
* Injects constants into JS. These constants are made accessible via
* NativeModules.ModuleName.X. This method is called when the module is

View File

@ -14,13 +14,11 @@
@implementation RCTTabBarManager
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE()
- (UIView *)view
{
return [[RCTTabBar alloc] initWithEventDispatcher:_bridge.eventDispatcher];
return [[RCTTabBar alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
}
RCT_EXPORT_VIEW_PROPERTY(tintColor, UIColor)